diff --git a/doc/reference.conf b/doc/reference.conf index 768ce0b..a532fb0 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -658,18 +658,19 @@ channel { /* The serverhide block contains the options regarding serverhiding */ serverhide { - /* flatten links: this option will show all servers in /links appear - * that they are linked to this current server + /* flatten links: this option will hide various routing information + * and make all servers in /links appear that they are linked to + * this server. */ flatten_links = no; - /* links delay: how often to update the links file when it is - * flattened. + /* links delay: how long to wait before showing splits or new + * servers in a flattened /links output. */ links_delay = 5 minutes; - /* hidden: hide this server from a /links output on servers that - * support it. this allows hub servers to be hidden etc. + /* hidden: hide this server from a /links output on servers with + * flatten_links enabled. this allows hub servers to be hidden etc. */ hidden = no; diff --git a/extensions/README b/extensions/README index 51bd10c..331ea64 100644 --- a/extensions/README +++ b/extensions/README @@ -19,11 +19,14 @@ m_42.c - The Answer to Life, the Universe, and Everything. m_findforwards.c - Find channels that forward (+f) to a given channel. Syntax: FINDFORWARDS +m_identify.c - Identifies to NickServ or ChanServ + Syntax: IDENTIFY [nick|channel] + m_mkpasswd.c - MKPASSWD - generate a DES or MD5 encryption of a password Syntax: MKPASSWD [MD5|DES] m_ojoin.c - OJOIN - Join a channel through any modes or limits with - an optional status (@%+) + an optional status (@+) Syntax: OJOIN [status]<channel> m_olist.c - OLIST - Lists channels like LIST, but shows hidden @@ -45,7 +48,7 @@ example_module.c - An example module to be used for creating your own. Spy Modules ----------- -The following are the 'spy' parts, accessible via the +y usermode +The following are the 'spy' parts, accessible via the +y snomask spy_admin_notice.c - Spy on clients doing ADMIN spy_info_notice.c - Spy on clients doing INFO @@ -53,9 +56,7 @@ spy_links_notice.c - Spy on clients doing LINKS spy_motd_notice.c - Spy on clients doing MOTD spy_stats_notice.c - Spy on clients doing all STATS spy_stats_p_notice.c - Spy on clients doing STATS p only -spy_trace_notice.c - Spy on clients doing TRACE/LTRACE -spy_whois_notice.c - Spy on local clients who WHOIS you. -spy_whois_notice_global.c - Spy on remote clients who WHOIS you. +spy_trace_notice.c - Spy on clients doing TRACE Note: if you have both spy_stats_notice.c and spy_stats_p_notice.c loaded you will get two messages. @@ -66,3 +67,15 @@ Snomask Modules sno_farconnect.c - Remote client connect/exit notices (snomask +F) sno_globalkline.c - Global K/D/X-line activation notices sno_globaloper.c - Global oper-up notices +sno_whois.c - Spy on clients who WHOIS you seeing idle time (snomask +W). + +Extban Modules +-------------- + +extb_account.so - Account bans (+b $a[:mask]) +extb_canjoin.so - Banned from another channel (+b $j:mask) +extb_channel.so - Other-channel bans (+b $c:mask) +extb_extgecos.so - Extended ban (+b $x:mask) +extb_oper.so - Oper bans (+b $o) +extb_realname.so - Realname (gecos) bans (+b $r:mask) +extb_server.so - Server bans (+b $s:mask) diff --git a/include/cache.h b/include/cache.h index a3485ec..f60b5b9 100644 --- a/include/cache.h +++ b/include/cache.h @@ -9,8 +9,6 @@ #define CACHELINELEN 81 #define CACHEFILELEN 30 -/* two servernames, a gecos, three spaces, ":1", '\0' */ -#define LINKSLINELEN (HOSTLEN + HOSTLEN + REALLEN + 6) #define HELP_USER 0x001 #define HELP_OPER 0x002 @@ -33,13 +31,11 @@ struct cacheline extern struct cachefile *user_motd; extern struct cachefile *oper_motd; extern struct cacheline *emptyline; -extern dlink_list links_cache_list; extern char user_motd_changed[MAX_DATE_STRING]; extern void init_cache(void); extern struct cachefile *cache_file(const char *, const char *, int); -extern void cache_links(void *unused); extern void free_cachefile(struct cachefile *); extern void load_help(void); diff --git a/include/client.h b/include/client.h index 3065c21..0b6adcc 100644 --- a/include/client.h +++ b/include/client.h @@ -69,6 +69,7 @@ struct LocalUser; struct AuthRequest; struct PreClient; struct ListClient; +struct scache_entry; /* * Atheme's coding standards require that we use BSD-style user-defined types @@ -107,6 +108,7 @@ struct Server dlink_list users; int caps; /* capabilities bit-field */ char *fullcaps; + struct scache_entry *nameinfo; }; struct SlinkRpl diff --git a/include/hostmask.h b/include/hostmask.h index ebd8bfc..191cce5 100644 --- a/include/hostmask.h +++ b/include/hostmask.h @@ -40,6 +40,8 @@ int parse_netmask(const char *, struct sockaddr *, int *); struct ConfItem *find_conf_by_address(const char *host, const char *sockhost, const char *orighost, struct sockaddr *, int, int, const char *); +struct ConfItem *find_exact_conf_by_address(const char *address, int type, + const char *username); void add_conf_by_address(const char *, int, const char *, struct ConfItem *); void delete_one_address_conf(const char *, struct ConfItem *); void clear_out_address_conf(void); diff --git a/include/s_conf.h b/include/s_conf.h index 846d2fe..2b69e6a 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -276,7 +276,6 @@ struct config_server_hide { int flatten_links; int links_delay; - int links_disabled; int hidden; int disable_hidden; }; diff --git a/include/s_newconf.h b/include/s_newconf.h index 6179535..ee25ac9 100644 --- a/include/s_newconf.h +++ b/include/s_newconf.h @@ -237,7 +237,9 @@ extern void set_server_conf_autoconn(struct Client *source_p, char *name, extern struct ConfItem *find_xline(const char *, int); +extern struct ConfItem *find_xline_mask(const char *); extern struct ConfItem *find_nick_resv(const char *name); +extern struct ConfItem *find_nick_resv_mask(const char *name); extern int valid_wild_card_simple(const char *); extern int clean_resv_nick(const char *); diff --git a/include/scache.h b/include/scache.h index 9c7fc27..eec241c 100644 --- a/include/scache.h +++ b/include/scache.h @@ -27,8 +27,15 @@ #ifndef INCLUDED_scache_h #define INCLUDED_scache_h +struct Client; +struct scache_entry; + extern void clear_scache_hash_table(void); -extern const char *find_or_add(const char *name); +extern struct scache_entry *scache_connect(const char *name, const char *info, int hidden); +extern void scache_split(struct scache_entry *ptr); +extern const char *scache_get_name(struct scache_entry *ptr); +extern void scache_send_flattened_links(struct Client *source_p); +extern void scache_send_missing(struct Client *source_p); extern void count_scache(size_t *, size_t *); #endif diff --git a/modules/core/m_nick.c b/modules/core/m_nick.c index 6fb0dba..ea91da2 100644 --- a/modules/core/m_nick.c +++ b/modules/core/m_nick.c @@ -1172,6 +1172,19 @@ register_client(struct Client *client_p, struct Client *server, const char *m; int flag; + if(server == NULL) + { + if((server = find_server(NULL, parv[7])) == NULL) + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Ghost killed: %s on invalid server %s", + nick, parv[7]); + sendto_one(client_p, ":%s KILL %s :%s (Server doesn't exist)", + get_id(&me, client_p), nick, me.name); + return 0; + } + } + source_p = make_client(client_p); user = make_user(source_p); dlinkAddTail(source_p, &source_p->node, &global_client_list); @@ -1265,20 +1278,7 @@ register_client(struct Client *client_p, struct Client *server, if(++Count.total > Count.max_tot) Count.max_tot = Count.total; - if(server == NULL) - { - if((source_p->servptr = find_server(NULL, server->name)) == NULL) - { - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Ghost killed: %s on invalid server %s", - source_p->name, server->name); - kill_client(client_p, source_p, "%s (Server doesn't exist)", me.name); - source_p->flags |= FLAGS_KILLED; - return exit_client(NULL, source_p, &me, "Ghosted Client"); - } - } - else - source_p->servptr = server; + source_p->servptr = server; dlinkAdd(source_p, &source_p->lnode, &source_p->servptr->serv->users); diff --git a/modules/core/m_server.c b/modules/core/m_server.c index 408fd06..8ccfeb3 100644 --- a/modules/core/m_server.c +++ b/modules/core/m_server.c @@ -38,6 +38,7 @@ #include "s_log.h" /* log level defines */ #include "s_serv.h" /* server_estab, check_server */ #include "s_stats.h" /* ServerStats */ +#include "scache.h" #include "send.h" /* sendto_one */ #include "msg.h" #include "parse.h" @@ -426,6 +427,8 @@ ms_server(struct Client *client_p, struct Client *source_p, int parc, const char add_to_client_hash(target_p->name, target_p); dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->servers); + target_p->serv->nameinfo = scache_connect(target_p->name, target_p->info, IsHidden(target_p)); + sendto_server(client_p, NULL, NOCAPS, NOCAPS, ":%s SERVER %s %d :%s%s", source_p->name, target_p->name, target_p->hopcount + 1, @@ -573,6 +576,8 @@ ms_sid(struct Client *client_p, struct Client *source_p, int parc, const char *p add_to_id_hash(target_p->id, target_p); dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->servers); + target_p->serv->nameinfo = scache_connect(target_p->name, target_p->info, IsHidden(target_p)); + sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s SID %s %d %s :%s%s", source_p->id, target_p->name, target_p->hopcount + 1, diff --git a/modules/m_dline.c b/modules/m_dline.c index f173d05..0237c13 100644 --- a/modules/m_dline.c +++ b/modules/m_dline.c @@ -63,7 +63,7 @@ DECLARE_MODULE_AV1(dline, NULL, NULL, dline_clist, NULL, NULL, "$Revision: 3225 static int valid_comment(char *comment); static int flush_write(struct Client *, FILE *, char *, char *); -static int remove_temp_dline(const char *); +static int remove_temp_dline(struct ConfItem *); /* mo_dline() * @@ -258,6 +258,7 @@ mo_undline(struct Client *client_p, struct Client *source_p, int parc, const cha char buf[BUFSIZE], buff[BUFSIZE], temppath[BUFSIZE], *p; const char *filename, *found_cidr; const char *cidr; + struct ConfItem *aconf; int pairme = NO, error_on_write = NO; mode_t oldumask; @@ -278,15 +279,23 @@ mo_undline(struct Client *client_p, struct Client *source_p, int parc, const cha return 0; } - if(remove_temp_dline(cidr)) + aconf = find_exact_conf_by_address(cidr, CONF_DLINE, NULL); + if(aconf == NULL) + { + sendto_one_notice(source_p, ":No D-Line for %s", cidr); + return 0; + } + + strlcpy(buf, aconf->host, sizeof buf); + if(remove_temp_dline(aconf)) { sendto_one(source_p, ":%s NOTICE %s :Un-dlined [%s] from temporary D-lines", - me.name, parv[0], cidr); + me.name, parv[0], buf); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has removed the temporary D-Line for: [%s]", - get_oper_name(source_p), cidr); - ilog(L_KLINE, "UD %s %s", get_oper_name(source_p), cidr); + get_oper_name(source_p), buf); + ilog(L_KLINE, "UD %s %s", get_oper_name(source_p), buf); return 0; } @@ -330,7 +339,7 @@ mo_undline(struct Client *client_p, struct Client *source_p, int parc, const cha continue; } - if(irccmp(found_cidr, cidr) == 0) + if(irccmp(found_cidr, aconf->host) == 0) { pairme++; } @@ -355,8 +364,8 @@ mo_undline(struct Client *client_p, struct Client *source_p, int parc, const cha } else if(!pairme) { - sendto_one(source_p, ":%s NOTICE %s :No D-Line for %s", - me.name, parv[0], cidr); + sendto_one_notice(source_p, ":Cannot find D-Line for %s in file", + aconf->host); if(temppath != NULL) (void) unlink(temppath); @@ -369,13 +378,13 @@ mo_undline(struct Client *client_p, struct Client *source_p, int parc, const cha sendto_one_notice(source_p, ":Couldn't rename temp file, aborted"); return 0; } - rehash_bans(0); - - sendto_one(source_p, ":%s NOTICE %s :D-Line for [%s] is removed", me.name, parv[0], cidr); + sendto_one(source_p, ":%s NOTICE %s :D-Line for [%s] is removed", me.name, parv[0], aconf->host); sendto_realops_snomask(SNO_GENERAL, L_ALL, - "%s has removed the D-Line for: [%s]", get_oper_name(source_p), cidr); - ilog(L_KLINE, "UD %s %s", get_oper_name(source_p), cidr); + "%s has removed the D-Line for: [%s]", get_oper_name(source_p), aconf->host); + ilog(L_KLINE, "UD %s %s", get_oper_name(source_p), aconf->host); + + delete_one_address_conf(aconf->host, aconf); return 0; } @@ -435,30 +444,21 @@ flush_write(struct Client *source_p, FILE * out, char *buf, char *temppath) /* remove_temp_dline() * - * inputs - hostname to undline + * inputs - confitem to undline * outputs - * side effects - tries to undline anything that matches */ static int -remove_temp_dline(const char *host) +remove_temp_dline(struct ConfItem *aconf) { - struct ConfItem *aconf; dlink_node *ptr; - struct irc_sockaddr_storage addr, caddr; - int bits, cbits; int i; - parse_netmask(host, (struct sockaddr *)&addr, &bits); - for (i = 0; i < LAST_TEMP_TYPE; i++) { DLINK_FOREACH(ptr, temp_dlines[i].head) { - aconf = ptr->data; - - parse_netmask(aconf->host, (struct sockaddr *)&caddr, &cbits); - - if(comp_with_mask_sock((struct sockaddr *)&addr, (struct sockaddr *)&caddr, bits) && bits == cbits) + if (aconf == ptr->data) { dlinkDestroy(ptr, &temp_dlines[i]); delete_one_address_conf(aconf->host, aconf); diff --git a/modules/m_gline.c b/modules/m_gline.c index 92d87d2..1d9ecb8 100644 --- a/modules/m_gline.c +++ b/modules/m_gline.c @@ -651,7 +651,7 @@ majority_gline(struct Client *source_p, const char *user, strlcpy(pending->oper_host2, source_p->host, sizeof(pending->oper_host2)); DupString(pending->reason2, reason); - pending->oper_server2 = find_or_add(source_p->servptr->name); + pending->oper_server2 = scache_get_name(source_p->servptr->serv->nameinfo); pending->last_gline_time = CurrentTime; pending->time_request2 = CurrentTime; return NO; @@ -670,7 +670,7 @@ majority_gline(struct Client *source_p, const char *user, strlcpy(pending->oper_host1, source_p->host, sizeof(pending->oper_host1)); - pending->oper_server1 = find_or_add(source_p->servptr->name); + pending->oper_server1 = scache_get_name(source_p->servptr->serv->nameinfo); strlcpy(pending->user, user, sizeof(pending->user)); strlcpy(pending->host, host, sizeof(pending->host)); diff --git a/modules/m_kline.c b/modules/m_kline.c index ff1eaed..401d600 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -83,9 +83,9 @@ static int already_placed_kline(struct Client *, const char *, const char *, int static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host); -static void remove_permkline_match(struct Client *, const char *, const char *); +static void remove_permkline_match(struct Client *, struct ConfItem *); static int flush_write(struct Client *, FILE *, const char *, const char *); -static int remove_temp_kline(const char *, const char *); +static int remove_temp_kline(struct ConfItem *); /* mo_kline() * @@ -353,6 +353,7 @@ mo_unkline(struct Client *client_p, struct Client *source_p, int parc, const cha char *host; char splat[] = "*"; char *h = LOCAL_COPY(parv[1]); + struct ConfItem *aconf; if(!IsOperUnkline(source_p)) { @@ -411,7 +412,14 @@ mo_unkline(struct Client *client_p, struct Client *source_p, int parc, const cha cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN, "%s %s", user, host); - if(remove_temp_kline(user, host)) + aconf = find_exact_conf_by_address(host, CONF_KILL, user); + if(aconf == NULL) + { + sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host); + return 0; + } + + if(remove_temp_kline(aconf)) { sendto_one_notice(source_p, ":Un-klined [%s@%s] from temporary k-lines", user, host); sendto_realops_snomask(SNO_GENERAL, L_ALL, @@ -422,7 +430,7 @@ mo_unkline(struct Client *client_p, struct Client *source_p, int parc, const cha return 0; } - remove_permkline_match(source_p, host, user); + remove_permkline_match(source_p, aconf); return 0; } @@ -465,11 +473,20 @@ me_unkline(struct Client *client_p, struct Client *source_p, int parc, const cha static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host) { + struct ConfItem *aconf; + if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_UNKLINE)) return; - if(remove_temp_kline(user, host)) + aconf = find_exact_conf_by_address(host, CONF_KILL, user); + if(aconf == NULL) + { + sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host); + return; + } + + if(remove_temp_kline(aconf)) { sendto_one_notice(source_p, ":Un-klined [%s@%s] from temporary k-lines", @@ -484,7 +501,7 @@ handle_remote_unkline(struct Client *source_p, const char *user, const char *hos return; } - remove_permkline_match(source_p, host, user); + remove_permkline_match(source_p, aconf); } /* apply_kline() @@ -739,7 +756,7 @@ already_placed_kline(struct Client *source_p, const char *luser, const char *lho * hunts for a permanent kline, and removes it. */ static void -remove_permkline_match(struct Client *source_p, const char *host, const char *user) +remove_permkline_match(struct Client *source_p, struct ConfItem *aconf) { FILE *in, *out; int pairme = 0; @@ -748,9 +765,13 @@ remove_permkline_match(struct Client *source_p, const char *host, const char *us char matchbuf[BUFSIZE]; char temppath[BUFSIZE]; const char *filename; + const char *host, *user; mode_t oldumask; int matchlen; + host = aconf->host; + user = aconf->user; + ircsnprintf(temppath, sizeof(temppath), "%s.tmp", ConfigFileEntry.klinefile); @@ -820,7 +841,7 @@ remove_permkline_match(struct Client *source_p, const char *host, const char *us } else if(!pairme) { - sendto_one_notice(source_p, ":No K-Line for %s@%s", + sendto_one_notice(source_p, ":Cannot find K-Line for %s@%s in file", user, host); if(temppath != NULL) @@ -834,7 +855,6 @@ remove_permkline_match(struct Client *source_p, const char *host, const char *us sendto_one_notice(source_p, ":Couldn't rename temp file, aborted"); return; } - rehash_bans(0); sendto_one_notice(source_p, ":K-Line for [%s@%s] is removed", user, host); @@ -845,6 +865,9 @@ remove_permkline_match(struct Client *source_p, const char *host, const char *us ilog(L_KLINE, "UK %s %s %s", get_oper_name(source_p), user, host); + + delete_one_address_conf(aconf->host, aconf); + return; } @@ -890,41 +913,21 @@ flush_write(struct Client *source_p, FILE * out, const char *buf, const char *te * side effects - tries to unkline anything that matches */ static int -remove_temp_kline(const char *user, const char *host) +remove_temp_kline(struct ConfItem *aconf) { - struct ConfItem *aconf; dlink_node *ptr; - struct irc_sockaddr_storage addr, caddr; - int bits, cbits; - int mtype, ktype; int i; - mtype = parse_netmask(host, (struct sockaddr *)&addr, &bits); - for (i = 0; i < LAST_TEMP_TYPE; i++) { DLINK_FOREACH(ptr, temp_klines[i].head) { - aconf = ptr->data; - - ktype = parse_netmask(aconf->host, (struct sockaddr *)&caddr, &cbits); - - if(ktype != mtype || (user && irccmp(user, aconf->user))) - continue; - - if(ktype == HM_HOST) + if (aconf == ptr->data) { - if(irccmp(aconf->host, host)) - continue; + dlinkDestroy(ptr, &temp_klines[i]); + delete_one_address_conf(aconf->host, aconf); + return YES; } - else if(bits != cbits || - !comp_with_mask_sock((struct sockaddr *)&addr, - (struct sockaddr *)&caddr, bits)) - continue; - - dlinkDestroy(ptr, &temp_klines[i]); - delete_one_address_conf(aconf->host, aconf); - return YES; } } diff --git a/modules/m_links.c b/modules/m_links.c index c7aaeea..295baa6 100644 --- a/modules/m_links.c +++ b/modules/m_links.c @@ -36,7 +36,7 @@ #include "parse.h" #include "modules.h" #include "hook.h" -#include "cache.h" +#include "scache.h" static int m_links(struct Client *, struct Client *, int, const char **); static int mo_links(struct Client *, struct Client *, int, const char **); @@ -56,8 +56,6 @@ mapi_hlist_av1 links_hlist[] = { DECLARE_MODULE_AV1(links, NULL, NULL, links_clist, links_hlist, NULL, "$Revision: 254 $"); -static void send_links_cache(struct Client *source_p); - /* * m_links - LINKS message handler * parv[0] = sender prefix @@ -71,7 +69,7 @@ static int m_links(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { if(ConfigServerHide.flatten_links && !IsExemptShide(source_p)) - send_links_cache(source_p); + scache_send_flattened_links(source_p); else mo_links(client_p, source_p, parc, parv); @@ -131,26 +129,3 @@ mo_links(struct Client *client_p, struct Client *source_p, int parc, const char return 0; } -/* send_links_cache() - * - * inputs - client to send to - * outputs - the cached links, us, and RPL_ENDOFLINKS - * side effects - - */ -static void -send_links_cache(struct Client *source_p) -{ - dlink_node *ptr; - - DLINK_FOREACH(ptr, links_cache_list.head) - { - sendto_one(source_p, ":%s 364 %s %s", - me.name, source_p->name, (const char *)ptr->data); - } - - sendto_one_numeric(source_p, RPL_LINKS, form_str(RPL_LINKS), - me.name, me.name, 0, me.info); - - sendto_one_numeric(source_p, RPL_ENDOFLINKS, form_str(RPL_ENDOFLINKS), "*"); -} - diff --git a/modules/m_map.c b/modules/m_map.c index aeb7c7f..256e3ad 100644 --- a/modules/m_map.c +++ b/modules/m_map.c @@ -29,6 +29,7 @@ #include "send.h" #include "s_conf.h" #include "sprintf_irc.h" +#include "scache.h" #define USER_COL 50 /* display | Users: %d at col 50 */ @@ -73,6 +74,7 @@ static int mo_map(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { dump_map(client_p, &me, buf); + scache_send_missing(client_p); sendto_one_numeric(client_p, RPL_MAPEND, form_str(RPL_MAPEND)); return 0; diff --git a/modules/m_resv.c b/modules/m_resv.c index 515d316..1659373 100644 --- a/modules/m_resv.c +++ b/modules/m_resv.c @@ -67,7 +67,7 @@ static void cluster_resv(struct Client *source_p, int temp_time, static void handle_remote_unresv(struct Client *source_p, const char *name); static void remove_resv(struct Client *source_p, const char *name); -static int remove_temp_resv(struct Client *source_p, const char *name); +static int remove_resv_from_file(struct Client *source_p, const char *name); /* * mo_resv() @@ -264,7 +264,7 @@ parse_resv(struct Client *source_p, const char *name, return; } - if(find_nick_resv(name)) + if(find_nick_resv_mask(name)) { sendto_one_notice(source_p, ":A RESV has already been placed on nick: %s", @@ -389,9 +389,6 @@ mo_unresv(struct Client *client_p, struct Client *source_p, int parc, const char cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", parv[1]); - if(remove_temp_resv(source_p, parv[1])) - return 0; - remove_resv(source_p, parv[1]); return 0; } @@ -438,30 +435,38 @@ handle_remote_unresv(struct Client *source_p, const char *name) source_p->servptr->name, SHARED_UNRESV)) return; - if(remove_temp_resv(source_p, name)) - return; - remove_resv(source_p, name); return; } -static int -remove_temp_resv(struct Client *source_p, const char *name) +static void +remove_resv(struct Client *source_p, const char *name) { struct ConfItem *aconf = NULL; if(IsChannelName(name)) { if((aconf = hash_find_resv(name)) == NULL) - return 0; + { + sendto_one_notice(source_p, ":No RESV for %s", name); + return; + } - /* its permanent, let remove_resv do it properly */ if(!aconf->hold) - return 0; - + { + if (!remove_resv_from_file(source_p, name)) + return; + } + else + { + sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the RESV for: [%s]", + get_oper_name(source_p), name); + ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); + } del_from_resv_hash(name, aconf); - free_conf(aconf); } else { @@ -478,35 +483,42 @@ remove_temp_resv(struct Client *source_p, const char *name) } if(aconf == NULL) - return 0; + { + sendto_one_notice(source_p, ":No RESV for %s", name); + return; + } - /* permanent, remove_resv() needs to do it properly */ if(!aconf->hold) - return 0; - + { + if (!remove_resv_from_file(source_p, name)) + return; + } + else + { + sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the RESV for: [%s]", + get_oper_name(source_p), name); + ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); + } /* already have ptr from the loop above.. */ dlinkDestroy(ptr, &resv_conf_list); - free_conf(aconf); } + free_conf(aconf); - sendto_one_notice(source_p, ":RESV for [%s] is removed", name); - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "%s has removed the RESV for: [%s]", - get_oper_name(source_p), name); - ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); - - return 1; + return; } -/* remove_resv() +/* remove_resv_from_file() * * inputs - client removing the resv * - resv to remove * outputs - - * side effects - resv if found, is removed + * side effects - resv if found, is removed from conf + * - does not touch resv hash or resv_conf_list */ -static void -remove_resv(struct Client *source_p, const char *name) +static int +remove_resv_from_file(struct Client *source_p, const char *name) { FILE *in, *out; char buf[BUFSIZE]; @@ -524,7 +536,7 @@ remove_resv(struct Client *source_p, const char *name) if((in = fopen(filename, "r")) == NULL) { sendto_one_notice(source_p, ":Cannot open %s", filename); - return; + return 0; } oldumask = umask(0); @@ -534,7 +546,7 @@ remove_resv(struct Client *source_p, const char *name) sendto_one_notice(source_p, ":Cannot open %s", temppath); fclose(in); umask(oldumask); - return; + return 0; } umask(oldumask); @@ -585,27 +597,28 @@ remove_resv(struct Client *source_p, const char *name) if(error_on_write) { sendto_one_notice(source_p, ":Couldn't write temp resv file, aborted"); - return; + return 0; } else if(!found_resv) { - sendto_one_notice(source_p, ":No RESV for %s", name); + sendto_one_notice(source_p, ":Cannot find RESV for %s in file", name); if(temppath != NULL) (void) unlink(temppath); - return; + return 0; } if (rename(temppath, filename)) { sendto_one_notice(source_p, ":Couldn't rename temp file, aborted"); - return; + return 0; } - rehash_bans(0); sendto_one_notice(source_p, ":RESV for [%s] is removed", name); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has removed the RESV for: [%s]", get_oper_name(source_p), name); ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); + + return 1; } diff --git a/modules/m_xline.c b/modules/m_xline.c index 7056137..37f4353 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -86,8 +86,8 @@ static void handle_remote_xline(struct Client *source_p, int temp_time, const char *name, const char *reason); static void handle_remote_unxline(struct Client *source_p, const char *name); -static int remove_temp_xline(struct Client *source_p, const char *name); -static void remove_xline(struct Client *source_p, const char *gecos); +static void remove_xline(struct Client *source_p, const char *name); +static int remove_xline_from_file(struct Client *source_p, const char *gecos); /* m_xline() @@ -156,10 +156,10 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char else if(dlink_list_length(&cluster_conf_list) > 0) cluster_xline(source_p, temp_time, name, reason); - if((aconf = find_xline(name, 0)) != NULL) + if((aconf = find_xline_mask(name)) != NULL) { sendto_one(source_p, ":%s NOTICE %s :[%s] already X-Lined by [%s] - %s", - me.name, source_p->name, parv[1], aconf->name, aconf->passwd); + me.name, source_p->name, name, aconf->name, aconf->passwd); return 0; } @@ -220,7 +220,7 @@ handle_remote_xline(struct Client *source_p, int temp_time, return; /* already xlined */ - if((aconf = find_xline(name, 0)) != NULL) + if((aconf = find_xline_mask(name)) != NULL) { sendto_one_notice(source_p, ":[%s] already X-Lined by [%s] - %s", name, aconf->name, aconf->passwd); return; @@ -478,9 +478,6 @@ mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const cha cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", parv[1]); - if(remove_temp_xline(source_p, parv[1])) - return 0; - remove_xline(source_p, parv[1]); return 0; @@ -527,16 +524,13 @@ handle_remote_unxline(struct Client *source_p, const char *name) source_p->servptr->name, SHARED_UNXLINE)) return; - if(remove_temp_xline(source_p, name)) - return; - remove_xline(source_p, name); return; } -static int -remove_temp_xline(struct Client *source_p, const char *name) +static void +remove_xline(struct Client *source_p, const char *name) { struct ConfItem *aconf; dlink_node *ptr; @@ -545,38 +539,45 @@ remove_temp_xline(struct Client *source_p, const char *name) { aconf = ptr->data; - /* only want to check temp ones! */ - if(!aconf->hold) - continue; - if(!irccmp(aconf->name, name)) { - sendto_one_notice(source_p, - ":X-Line for [%s] is removed", - name); - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "%s has removed the temporary X-Line for: [%s]", - get_oper_name(source_p), name); - ilog(L_KLINE, "UX %s %s", - get_oper_name(source_p), name); + if (!aconf->hold) + { + if (!remove_xline_from_file(source_p, name)) + return; + } + else + { + sendto_one_notice(source_p, + ":X-Line for [%s] is removed", + name); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the temporary X-Line for: [%s]", + get_oper_name(source_p), name); + ilog(L_KLINE, "UX %s %s", + get_oper_name(source_p), name); + } free_conf(aconf); dlinkDestroy(ptr, &xline_conf_list); - return 1; + return; } } - return 0; + sendto_one_notice(source_p, ":No X-Line for %s", name); + + return; } -/* remove_xline() +/* remove_xline_from_file() * * inputs - gecos to remove * outputs - * side effects - removes xline from conf, if exists + * - does not touch xline_conf_list */ -static void -remove_xline(struct Client *source_p, const char *huntgecos) +static int +remove_xline_from_file(struct Client *source_p, const char *huntgecos) { FILE *in, *out; char buf[BUFSIZE]; @@ -596,7 +597,7 @@ remove_xline(struct Client *source_p, const char *huntgecos) if((in = fopen(filename, "r")) == NULL) { sendto_one_notice(source_p, ":Cannot open %s", filename); - return; + return 0; } oldumask = umask(0); @@ -606,7 +607,7 @@ remove_xline(struct Client *source_p, const char *huntgecos) sendto_one_notice(source_p, ":Cannot open %s", temppath); fclose(in); umask(oldumask); - return; + return 0; } umask(oldumask); @@ -653,27 +654,28 @@ remove_xline(struct Client *source_p, const char *huntgecos) { sendto_one_notice(source_p, ":Couldn't write temp xline file, aborted"); - return; + return 0; } else if(found_xline == 0) { - sendto_one_notice(source_p, ":No X-Line for %s", huntgecos); + sendto_one_notice(source_p, ":Cannot find X-Line for %s in file", huntgecos); if(temppath != NULL) (void) unlink(temppath); - return; + return 0; } if (rename(temppath, filename)) { sendto_one_notice(source_p, ":Couldn't rename temp file, aborted"); - return; + return 0; } - rehash_bans(0); sendto_one_notice(source_p, ":X-Line for [%s] is removed", huntgecos); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has removed the X-Line for: [%s]", get_oper_name(source_p), huntgecos); ilog(L_KLINE, "UX %s %s", get_oper_name(source_p), huntgecos); + + return 1; } diff --git a/src/cache.c b/src/cache.c index 0a23ebb..c55364a 100644 --- a/src/cache.c +++ b/src/cache.c @@ -50,7 +50,6 @@ static BlockHeap *cacheline_heap = NULL; struct cachefile *user_motd = NULL; struct cachefile *oper_motd = NULL; -dlink_list links_cache_list; char user_motd_changed[MAX_DATE_STRING]; /* init_cache() @@ -69,7 +68,6 @@ init_cache(void) user_motd = cache_file(MPATH, "ircd.motd", 0); oper_motd = cache_file(OPATH, "opers.motd", 0); - memset(&links_cache_list, 0, sizeof(links_cache_list)); } /* cache_file() @@ -131,43 +129,6 @@ cache_file(const char *filename, const char *shortname, int flags) return cacheptr; } -void -cache_links(void *unused) -{ - struct Client *target_p; - dlink_node *ptr; - dlink_node *next_ptr; - char *links_line; - - DLINK_FOREACH_SAFE(ptr, next_ptr, links_cache_list.head) - { - MyFree(ptr->data); - free_dlink_node(ptr); - } - - links_cache_list.head = links_cache_list.tail = NULL; - links_cache_list.length = 0; - - DLINK_FOREACH(ptr, global_serv_list.head) - { - target_p = ptr->data; - - /* skip ourselves (done in /links) and hidden servers */ - if(IsMe(target_p) || - (IsHidden(target_p) && !ConfigServerHide.disable_hidden)) - continue; - - /* if the below is ever modified, change LINKSLINELEN */ - links_line = MyMalloc(LINKSLINELEN); - ircsnprintf(links_line, LINKSLINELEN, "%s %s :1 %s", - target_p->name, me.name, - target_p->info[0] ? target_p->info : - "(Unknown Location)"); - - dlinkAddTailAlloc(links_line, &links_cache_list); - } -} - /* free_cachefile() * * inputs - cachefile to free diff --git a/src/client.c b/src/client.c index bdebefc..bb0f472 100644 --- a/src/client.c +++ b/src/client.c @@ -59,6 +59,7 @@ #include "monitor.h" #include "blacklist.h" #include "reject.h" +#include "scache.h" #define DEBUG_EXITED_CLIENTS @@ -1487,6 +1488,7 @@ exit_remote_server(struct Client *client_p, struct Client *source_p, struct Clie del_from_client_hash(source_p->name, source_p); remove_client_from_list(source_p); + scache_split(source_p->serv->nameinfo); SetDead(source_p); #ifdef DEBUG_EXITED_CLIENTS @@ -1583,6 +1585,7 @@ exit_local_server(struct Client *client_p, struct Client *source_p, struct Clien del_from_client_hash(source_p->name, source_p); remove_client_from_list(source_p); + scache_split(source_p->serv->nameinfo); SetDead(source_p); dlinkAddAlloc(source_p, &dead_list); diff --git a/src/hostmask.c b/src/hostmask.c index 334be58..bcbe064 100644 --- a/src/hostmask.c +++ b/src/hostmask.c @@ -432,6 +432,62 @@ find_dline(struct sockaddr *addr, int aftype) return find_conf_by_address(NULL, NULL, NULL, addr, CONF_DLINE | 1, aftype, NULL); } +/* void find_exact_conf_by_address(const char*, int, const char *) + * Input: + * Output: ConfItem if found + * Side-effects: None + */ +struct ConfItem * +find_exact_conf_by_address(const char *address, int type, const char *username) +{ + int masktype, bits; + unsigned long hv; + struct AddressRec *arec; + struct irc_sockaddr_storage addr; + + if(address == NULL) + address = "/NOMATCH!/"; + arec = MyMalloc(sizeof(struct AddressRec)); + masktype = parse_netmask(address, (struct sockaddr *)&addr, &bits); +#ifdef IPV6 + if(masktype == HM_IPV6) + { + /* We have to do this, since we do not re-hash for every bit -A1kmm. */ + hv = hash_ipv6((struct sockaddr *)&addr, bits - bits % 16); + } + else +#endif + if(masktype == HM_IPV4) + { + /* We have to do this, since we do not re-hash for every bit -A1kmm. */ + hv = hash_ipv4((struct sockaddr *)&addr, bits - bits % 8); + } + else + { + hv = get_mask_hash(address); + } + for (arec = atable[hv]; arec; arec = arec->next) + { + if (arec->type == type && + arec->masktype == masktype && + (arec->username == NULL || username == NULL ? arec->username == username : !irccmp(arec->username, username))) + { + if (masktype == HM_HOST) + { + if (!irccmp(arec->Mask.hostname, address)) + return arec->aconf; + } + else + { + if (arec->Mask.ipa.bits == bits && + comp_with_mask_sock((struct sockaddr *)&arec->Mask.ipa.addr, (struct sockaddr *)&addr, bits)) + return arec->aconf; + } + } + } + return NULL; +} + /* void add_conf_by_address(const char*, int, const char *, * struct ConfItem *aconf) * Input: diff --git a/src/ircd.c b/src/ircd.c index 75e689e..a134e91 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -638,6 +638,7 @@ main(int argc, char *argv[]) startup_time = CurrentTime; add_to_client_hash(me.name, &me); add_to_id_hash(me.id, &me); + me.serv->nameinfo = scache_connect(me.name, me.info, 0); dlinkAddAlloc(&me, &global_serv_list); @@ -667,12 +668,6 @@ main(int argc, char *argv[]) eventAdd("check_rehash", check_rehash, NULL, 1); - if(ConfigServerHide.links_delay > 0) - eventAdd("cache_links", cache_links, NULL, - ConfigServerHide.links_delay); - else - ConfigServerHide.links_disabled = 1; - if(splitmode) eventAdd("check_splitmode", check_splitmode, NULL, 2); diff --git a/src/kdparse.c b/src/kdparse.c index 258b666..ee95d39 100644 --- a/src/kdparse.c +++ b/src/kdparse.c @@ -177,7 +177,7 @@ parse_x_file(FILE * file) continue; /* sanity checking */ - if((find_xline(gecos_field, 0) != NULL) || + if((find_xline_mask(gecos_field) != NULL) || (strchr(reason_field, ':') != NULL)) continue; @@ -231,7 +231,7 @@ parse_resv_file(FILE * file) } else if(clean_resv_nick(host_field)) { - if(find_nick_resv(host_field)) + if(find_nick_resv_mask(host_field)) continue; aconf = make_conf(); diff --git a/src/newconf.c b/src/newconf.c index 8c1e52b..4f64205 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -1528,14 +1528,6 @@ conf_set_serverhide_links_delay(void *data) { int val = *(unsigned int *) data; - if((val > 0) && ConfigServerHide.links_disabled == 1) - { - eventAddIsh("cache_links", cache_links, NULL, val); - ConfigServerHide.links_disabled = 0; - } - else if(val != ConfigServerHide.links_delay) - eventUpdate("cache_links", val); - ConfigServerHide.links_delay = val; } diff --git a/src/s_newconf.c b/src/s_newconf.c index 4b5e1e0..dc0474d 100644 --- a/src/s_newconf.c +++ b/src/s_newconf.c @@ -528,6 +528,23 @@ find_xline(const char *gecos, int counter) return NULL; } +struct ConfItem * +find_xline_mask(const char *gecos) +{ + struct ConfItem *aconf; + dlink_node *ptr; + + DLINK_FOREACH(ptr, xline_conf_list.head) + { + aconf = ptr->data; + + if(!irccmp(aconf->name, gecos)) + return aconf; + } + + return NULL; +} + struct ConfItem * find_nick_resv(const char *name) { @@ -548,6 +565,23 @@ find_nick_resv(const char *name) return NULL; } +struct ConfItem * +find_nick_resv_mask(const char *name) +{ + struct ConfItem *aconf; + dlink_node *ptr; + + DLINK_FOREACH(ptr, resv_conf_list.head) + { + aconf = ptr->data; + + if(!irccmp(aconf->name, name)) + return aconf; + } + + return NULL; +} + /* clean_resv_nick() * * inputs - nick diff --git a/src/s_serv.c b/src/s_serv.c index 582d154..df8dfe4 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -1117,6 +1117,7 @@ server_estab(struct Client *client_p) client_p->localClient->fullcaps = NULL; } + client_p->serv->nameinfo = scache_connect(client_p->name, client_p->info, IsHidden(client_p)); client_p->localClient->firsttime = CurrentTime; /* fixing eob timings.. -gnp */ diff --git a/src/scache.c b/src/scache.c index 0819bbd..525e5bd 100644 --- a/src/scache.c +++ b/src/scache.c @@ -33,6 +33,7 @@ #include "send.h" #include "scache.h" #include "memory.h" +#include "s_conf.h" /* @@ -42,19 +43,29 @@ * in its lifetime is at most a few hundred. by tokenizing server * names internally, the server can easily save 2 or 3 megs of RAM. * -orabidoo + * + * reworked to serve for flattening/delaying /links also + * -- jilles */ #define SCACHE_HASH_SIZE 257 -typedef struct scache_entry +#define SC_ONLINE 1 +#define SC_HIDDEN 2 + +struct scache_entry { char name[HOSTLEN + 1]; + char info[REALLEN + 1]; + int flags; + time_t known_since; + time_t last_connect; + time_t last_split; struct scache_entry *next; -} -SCACHE; +}; -static SCACHE *scache_hash[SCACHE_HASH_SIZE]; +static struct scache_entry *scache_hash[SCACHE_HASH_SIZE]; void clear_scache_hash_table(void) @@ -76,37 +87,131 @@ sc_hash(const char *string) return hash_value % SCACHE_HASH_SIZE; } -/* - * this takes a server name, and returns a pointer to the same string - * (up to case) in the server name token list, adding it to the list if - * it's not there. care must be taken not to call this with - * user-supplied arguments that haven't been verified to be a valid, - * existing, servername. use the hash in list.c for those. -orabidoo - */ - -const char * +static struct scache_entry * find_or_add(const char *name) { int hash_index; - SCACHE *ptr; + struct scache_entry *ptr; ptr = scache_hash[hash_index = sc_hash(name)]; for (; ptr; ptr = ptr->next) { if(!irccmp(ptr->name, name)) - return (ptr->name); + return ptr; } - ptr = (SCACHE *) MyMalloc(sizeof(SCACHE)); + ptr = (struct scache_entry *) MyMalloc(sizeof(struct scache_entry)); s_assert(0 != ptr); strlcpy(ptr->name, name, sizeof(ptr->name)); + ptr->info[0] = '\0'; + ptr->flags = 0; + ptr->known_since = CurrentTime; + ptr->last_connect = 0; + ptr->last_split = 0; ptr->next = scache_hash[hash_index]; scache_hash[hash_index] = ptr; + return ptr; +} + +struct scache_entry * +scache_connect(const char *name, const char *info, int hidden) +{ + struct scache_entry *ptr; + + ptr = find_or_add(name); + strlcpy(ptr->info, info, sizeof(ptr->info)); + ptr->flags |= SC_ONLINE; + if (hidden) + ptr->flags |= SC_HIDDEN; + else + ptr->flags &= ~SC_HIDDEN; + ptr->last_connect = CurrentTime; + return ptr; +} + +void +scache_split(struct scache_entry *ptr) +{ + if (ptr == NULL) + return; + ptr->flags &= ~SC_ONLINE; + ptr->last_split = CurrentTime; +} + +const char *scache_get_name(struct scache_entry *ptr) +{ return ptr->name; } +/* scache_send_flattened_links() + * + * inputs - client to send to + * outputs - the cached links, us, and RPL_ENDOFLINKS + * side effects - + */ +void +scache_send_flattened_links(struct Client *source_p) +{ + struct scache_entry *scache_ptr; + int i; + int show; + + for (i = 0; i < SCACHE_HASH_SIZE; i++) + { + scache_ptr = scache_hash[i]; + while (scache_ptr) + { + if (!irccmp(scache_ptr->name, me.name)) + show = FALSE; + else if (scache_ptr->flags & SC_HIDDEN && + !ConfigServerHide.disable_hidden) + show = FALSE; + else if (scache_ptr->flags & SC_ONLINE) + show = scache_ptr->known_since < CurrentTime - ConfigServerHide.links_delay; + else + show = scache_ptr->last_split > CurrentTime - ConfigServerHide.links_delay && scache_ptr->last_split - scache_ptr->known_since > ConfigServerHide.links_delay; + if (show) + sendto_one_numeric(source_p, RPL_LINKS, form_str(RPL_LINKS), + scache_ptr->name, me.name, 1, scache_ptr->info); + + scache_ptr = scache_ptr->next; + } + } + sendto_one_numeric(source_p, RPL_LINKS, form_str(RPL_LINKS), + me.name, me.name, 0, me.info); + + sendto_one_numeric(source_p, RPL_ENDOFLINKS, form_str(RPL_ENDOFLINKS), "*"); +} + +#define MISSING_TIMEOUT 86400 + +/* scache_send_missing() + * + * inputs - client to send to + * outputs - recently split servers + * side effects - + */ +void +scache_send_missing(struct Client *source_p) +{ + struct scache_entry *scache_ptr; + int i; + + for (i = 0; i < SCACHE_HASH_SIZE; i++) + { + scache_ptr = scache_hash[i]; + while (scache_ptr) + { + if (!(scache_ptr->flags & SC_ONLINE) && scache_ptr->last_split > CurrentTime - MISSING_TIMEOUT) + sendto_one_numeric(source_p, RPL_MAP, "** %s (recently split)", + scache_ptr->name); + + scache_ptr = scache_ptr->next; + } + } +} /* * count_scache * inputs - pointer to where to leave number of servers cached @@ -117,7 +222,7 @@ find_or_add(const char *name) void count_scache(size_t * number_servers_cached, size_t * mem_servers_cached) { - SCACHE *scache_ptr; + struct scache_entry *scache_ptr; int i; *number_servers_cached = 0; @@ -130,7 +235,7 @@ count_scache(size_t * number_servers_cached, size_t * mem_servers_cached) { *number_servers_cached = *number_servers_cached + 1; *mem_servers_cached = *mem_servers_cached + - (strlen(scache_ptr->name) + sizeof(SCACHE *)); + sizeof(struct scache_entry ); scache_ptr = scache_ptr->next; } diff --git a/src/whowas.c b/src/whowas.c index d72cea1..880826f 100644 --- a/src/whowas.c +++ b/src/whowas.c @@ -87,7 +87,7 @@ void add_history(struct Client *client_p, int online) else who->sockhost[0] = '\0'; - who->servername = find_or_add(client_p->servptr->name); + who->servername = scache_get_name(client_p->servptr->serv->nameinfo); if(online) {