diff options
-rw-r--r-- | Changes | 1 | ||||
-rw-r--r-- | Changes.conf | 26 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | botserv.c | 21 | ||||
-rw-r--r-- | channels.c | 31 | ||||
-rw-r--r-- | chanserv.c | 124 | ||||
-rw-r--r-- | config.c | 2 | ||||
-rw-r--r-- | data/example.conf | 17 | ||||
-rw-r--r-- | docs/README | 5 | ||||
-rw-r--r-- | extern.h | 27 | ||||
-rw-r--r-- | init.c | 7 | ||||
-rw-r--r-- | messages.c | 39 | ||||
-rw-r--r-- | nickserv.c | 27 | ||||
-rw-r--r-- | operserv.c | 91 | ||||
-rw-r--r-- | send.c | 38 | ||||
-rw-r--r-- | servers.c | 259 | ||||
-rw-r--r-- | services.h | 31 | ||||
-rw-r--r-- | users.c | 48 | ||||
-rw-r--r-- | version.log | 7 | ||||
-rw-r--r-- | version.sh | 2 |
20 files changed, 625 insertions, 183 deletions
@@ -1,6 +1,7 @@ Anope Version S V N ------------------- Provided by Anope Dev. <dev@anope.org> - 2004 +06/18 A Added proper Bahamut1.8 support. [ #55] Anope Version 1.7.4 ------------------- diff --git a/Changes.conf b/Changes.conf index 1c16c368b..57de5ffc3 100644 --- a/Changes.conf +++ b/Changes.conf @@ -1,7 +1,33 @@ Anope Version S V N ------------------- ** ADDED CONFIGURATION DIRECTIVES ** + +# UseSVSHOLD [OPTIONAL] +# Allows Bahamut-networks to use SVSHOLD instead of the services +# enforcer. This option has been introduced in Bahamut 1.4.35 and +# places a temporary Q:Line instead of introducing a new nick, +# which is better for both CPU and bandwidth. If you enable this +# option on a pre-1.4.35 Bahamut, it is most likely to break. +#UseSVSHOLD + ** MODIFIED CONFIGURATION DIRECTIVES ** + +# NetworkDomain <name> [OPTIONAL] +# +# If your network has a common domain name, specify it there (for +# example, all IRCZONE servers have a name ending in ".irczone.cl", +# so "irczone.cl" would be set there. +# +# You can specify more than one Network Domain by separating each one by +# a space: NetworkDomain "localnet.net localnet.com" +# +# Note that this directive is no longer used by the GLOBAL command, since +# it uses a dynamic list of connected servers regardless of their +# domains. However, some modules may still use this value, so you might +# want to keep it just in case. + +NetworkDomain "localnet.com" + ** DELETED CONFIGURATION DIRECTIVES ** Anope Version 1.7.4 @@ -40,13 +40,13 @@ CFLAGS = $(CDEFS) $(BASE_CFLAGS) $(MORE_CFLAGS) OBJS = actions.o botserv.o channels.o chanserv.o commands.o compat.o converter.o \ config.o datafiles.o encrypt.o helpserv.o hostserv.o init.o language.o list.o log.o mail.o main.o \ memory.o memoserv.o messages.o misc.o modules.o news.o nickserv.o operserv.o \ - process.o protocol.o proxy.o send.o sessions.o slist.o sockutil.o \ + process.o protocol.o proxy.o send.o servers.o sessions.o slist.o sockutil.o \ timeout.o users.o \ $(VSNPRINTF_O) $(RDB_O) $(MYSQL_O) SRCS = actions.c botserv.c channels.c chanserv.c commands.c compat.c converter.c \ config.c datafiles.c encrypt.c helpserv.c hostserv.c init.c language.c list.c log.c mail.c main.c \ memory.c memoserv.c messages.c misc.c modules.c news.c nickserv.c operserv.c \ - process.c protocol.c proxy.c send.c sessions.c slist.c sockutil.c \ + process.c protocol.c proxy.c send.c servers.c sessions.c slist.c sockutil.c \ timeout.c users.c \ $(VSNPRINTF_C) $(RDB_C) $(MYSQL_C) @@ -143,6 +143,7 @@ process.o: process.c services.h messages.h protocol.o: protocol.c services.h proxy.o: proxy.c services.h pseudo.h send.o: send.c services.h +servers.o: servers.c services.h sessions.o: sessions.c services.h pseudo.h slist.o: slist.c services.h slist.h sockutil.o: sockutil.c services.h @@ -952,8 +952,7 @@ void bot_join(ChannelInfo * ci) av[1] = sstrdup("-b"); for (i = 0; i < count; i++) { if (match_wild_nocase(ci->c->bans[i], botmask)) { - send_cmd(ci->bi->nick, "MODE %s -b %s", ci->name, - bans[i]); + send_mode(ci->bi->nick, ci->name, "%s", bans[i]); av[2] = sstrdup(bans[i]); do_cmode(ci->bi->nick, 3, av); free(av[2]); @@ -980,14 +979,14 @@ void bot_join(ChannelInfo * ci) #endif #if defined(IRC_UNREAL) || defined (IRC_VIAGRA) - send_cmd(ci->bi->nick, "MODE %s +ao %s %s", ci->c->name, ci->bi->nick, - ci->bi->nick); + send_mode(ci->bi->nick, ci->c->name, "+ao %s %s", ci->bi->nick, + ci->bi->nick); #elif defined(IRC_PTLINK) /* PTLinks requieres an IRCop to u-line changes, so use ChanServ */ - send_cmd(s_ChanServ, "MODE %s +ao %s %s", ci->c->name, ci->bi->nick, - ci->bi->nick); + send_mode(s_ChanServ, ci->c->name, "+ao %s %s", ci->bi->nick, + ci->bi->nick); #else - send_cmd(ci->bi->nick, "MODE %s +o %s", ci->c->name, ci->bi->nick); + send_mode(ci->bi->nick, ci->c->name, "+o %s", ci->bi->nick); #endif } @@ -1031,7 +1030,7 @@ static void check_ban(ChannelInfo * ci, User * u, int ttbtype) av[1] = sstrdup("+b"); get_idealban(ci, u, mask, sizeof(mask)); av[2] = mask; - send_cmd(ci->bi->nick, "MODE %s +b %s", av[0], av[2]); + send_mode(ci->bi->nick, av[0], "+b %s", av[2]); do_cmode(ci->bi->nick, 3, av); free(av[1]); } @@ -1102,7 +1101,7 @@ static void bot_raw_ban(User * requester, ChannelInfo * ci, char *nick, av[1] = sstrdup("+b"); get_idealban(ci, u, mask, sizeof(mask)); av[2] = mask; - send_cmd(ci->bi->nick, "MODE %s +b %s", av[0], av[2]); + send_mode(ci->bi->nick, av[0], "+b %s", av[2]); do_cmode(ci->bi->nick, 3, av); free(av[1]); @@ -1191,7 +1190,7 @@ static void bot_raw_mode(User * requester, ChannelInfo * ci, char *mode, av[1] = mode; av[2] = nick; - send_cmd(ci->bi->nick, "MODE %s %s %s", av[0], av[1], av[2]); + send_mode(ci->bi->nick, av[0], "%s %s", av[1], av[2]); do_cmode(ci->bi->nick, 3, av); } @@ -1227,7 +1226,7 @@ static void bot_raw_unban(ChannelInfo * ci, char *nick) for (i = 0; i < count; i++) { if (match_usermask(bans[i], u)) { - send_cmd(ci->bi->nick, "MODE %s -b %s", ci->name, bans[i]); + send_mode(ci->bi->nick, ci->name, "-b %s", bans[i]); av[2] = bans[i]; do_cmode(ci->bi->nick, 3, av); } diff --git a/channels.c b/channels.c index 61d4c33d1..9e51ba9e6 100644 --- a/channels.c +++ b/channels.c @@ -593,8 +593,8 @@ void chan_set_modes(const char *source, Channel * chan, int ac, char **av, BotInfo *bi; if ((bi = findbot(*av))) { - send_cmd(bi->nick, "MODE %s +%c %s", chan->name, mode, - bi->nick); + send_mode(bi->nick, chan->name, "+%c %s", mode, + bi->nick); continue; } } @@ -1114,6 +1114,29 @@ void do_cmode(const char *source, int ac, char **av) { Channel *chan; ChannelInfo *ci = NULL; +#ifdef IRC_BAHAMUT + int i; + char *t; + + /* TSMODE for bahamut - leave this code out to break MODEs. -GD */ + if (uplink_capab & CAPAB_TSMODE) { + for (i = 0; i < strlen(av[1]); i++) { + if (!isdigit(av[1][i])) + break; + } + if (av[1][i] == '\0') { + /* We have a valid TS field in av[1] now, so we can strip it off */ + /* After we swap av[0] and av[1] ofcourse to not break stuff! :) */ + t = av[0]; + av[0] = av[1]; + av[1] = t; + ac--; + av++; + } else { + alog("TSMODE enabled but MODE has no valid TS"); + } + } +#endif chan = findchan(av[0]); if (!chan) { @@ -1183,7 +1206,7 @@ static void add_ban(Channel * chan, char *mask) snprintf(botmask, sizeof(botmask), "%s!%s@%s", bi->nick, bi->user, bi->host); if (match_wild_nocase(mask, botmask)) { - send_cmd(bi->nick, "MODE %s -b %s", chan->name, mask); + send_mode(bi->nick, chan->name, "-b %s", mask); return; } } @@ -1597,7 +1620,7 @@ void do_mass_mode(char *modes) if (c->bouncy_modes) { return; } else { - send_cmd(s_OperServ, "MODE %s %s", c->name, modes); + send_mode(s_OperServ, c->name, "%s", modes); chan_set_modes(s_OperServ, c, ac, av, 1); } } diff --git a/chanserv.c b/chanserv.c index 19e7d6b71..06236c547 100644 --- a/chanserv.c +++ b/chanserv.c @@ -1351,7 +1351,7 @@ void check_modes(Channel * c) #ifndef IRC_HYBRID if (c->mode & CMODE_r) { c->mode &= ~CMODE_r; - send_cmd(whosends(ci), "MODE %s -r", c->name); + send_mode(whosends(ci), c->name, "-r"); } #endif return; @@ -1440,8 +1440,8 @@ void check_modes(Channel * c) *end = 0; *end2 = 0; - send_cmd(whosends(ci), "MODE %s %s%s", c->name, modebuf, - (end2 == argbuf ? "" : argbuf)); + send_mode(whosends(ci), c->name, "%s%s", modebuf, + (end2 == argbuf ? "" : argbuf)); } /*************************************************************************/ @@ -1459,14 +1459,12 @@ int check_valid_admin(User * user, Channel * chan, int servermode) if (servermode && !check_access(user, chan->ci, CA_AUTOPROTECT)) { notice_lang(s_ChanServ, user, CHAN_IS_REGISTERED, s_ChanServ); - send_cmd(whosends(chan->ci), "MODE %s -a %s", chan->name, - user->nick); + send_mode(whosends(chan->ci), chan->name, "-a %s", user->nick); return 0; } if (check_access(user, chan->ci, CA_AUTODEOP)) { - send_cmd(whosends(chan->ci), "MODE %s -a %s", chan->name, - user->nick); + send_mode(whosends(chan->ci), chan->name, "-a %s", user->nick); return 0; } @@ -1494,33 +1492,30 @@ int check_valid_op(User * user, Channel * chan, int servermode) #ifdef HAS_HALFOP # if defined(IRC_UNREAL) if (check_access(user, chan->ci, CA_AUTOHALFOP)) { - send_cmd(whosends(chan->ci), "MODE %s -aoq %s %s %s", - chan->name, user->nick, user->nick, user->nick); + send_mode(whosends(chan->ci), chan->name, "-aoq %s %s %s", + user->nick, user->nick, user->nick); } else { - send_cmd(whosends(chan->ci), "MODE %s -ahoq %s %s %s %s", - chan->name, user->nick, user->nick, user->nick, - user->nick); + send_mode(whosends(chan->ci), chan->name, "-ahoq %s %s %s %s", + user->nick, user->nick, user->nick, user->nick); } # elif defined(IRC_ULTIMATE3) || defined(IRC_RAGE2) if (check_access(user, chan->ci, CA_AUTOHALFOP)) { - send_cmd(whosends(chan->ci), "MODE %s -ao %s %s", - chan->name, user->nick, user->nick); + send_mode(whosends(chan->ci), chan->name, "-ao %s %s", + user->nick, user->nick); } else { - send_cmd(whosends(chan->ci), "MODE %s -aoh %s %s %s", - chan->name, user->nick, user->nick, user->nick); + send_mode(whosends(chan->ci), chan->name, "-aoh %s %s %s", + user->nick, user->nick, user->nick); } # else if (check_access(user, chan->ci, CA_AUTOHALFOP)) { - send_cmd(whosends(chan->ci), "MODE %s -o %s", chan->name, - user->nick); + send_mode(whosends(chan->ci), chan->name, "-o %s", user->nick); } else { - send_cmd(whosends(chan->ci), "MODE %s -ho %s %s", chan->name, - user->nick, user->nick); + send_mode(whosends(chan->ci), chan->name, "-ho %s %s", + user->nick, user->nick); } # endif #else - send_cmd(whosends(chan->ci), "MODE %s -o %s", chan->name, - user->nick); + send_mode(whosends(chan->ci), chan->name, "-o %s", user->nick); #endif return 0; } @@ -1528,16 +1523,14 @@ int check_valid_op(User * user, Channel * chan, int servermode) if (check_access(user, chan->ci, CA_AUTODEOP)) { #ifdef HAS_HALFOP # ifdef IRC_UNREAL - send_cmd(whosends(chan->ci), "MODE %s -ahoq %s %s %s %s", - chan->name, user->nick, user->nick, user->nick, - user->nick); + send_mode(whosends(chan->ci), chan->name, "-ahoq %s %s %s %s", + user->nick, user->nick, user->nick, user->nick); # else - send_cmd(whosends(chan->ci), "MODE %s -ho %s %s", chan->name, - user->nick, user->nick); + send_mode(whosends(chan->ci), chan->name, "-ho %s %s", user->nick, + user->nick); # endif #else - send_cmd(whosends(chan->ci), "MODE %s -o %s", chan->name, - user->nick); + send_mode(whosends(chan->ci), chan->name, "-o %s", user->nick); #endif return 0; } @@ -1562,7 +1555,7 @@ int check_should_op(User * user, const char *chan) return 0; if (check_access(user, ci, CA_AUTOOP)) { - send_cmd(whosends(ci), "MODE %s +o %s", chan, user->nick); + send_mode(whosends(ci), chan, "+o %s", user->nick); return 1; } @@ -1585,7 +1578,7 @@ int check_should_voice(User * user, const char *chan) return 0; if (check_access(user, ci, CA_AUTOVOICE)) { - send_cmd(whosends(ci), "MODE %s +v %s", chan, user->nick); + send_mode(whosends(ci), chan, "+v %s", user->nick); return 1; } @@ -1604,7 +1597,7 @@ int check_should_halfop(User * user, const char *chan) return 0; if (check_access(user, ci, CA_AUTOHALFOP)) { - send_cmd(whosends(ci), "MODE %s +h %s", chan, user->nick); + send_mode(whosends(ci), chan, "+h %s", user->nick); return 1; } @@ -1626,8 +1619,7 @@ int check_should_owner(User * user, const char *chan) if (((ci->flags & CI_SECUREFOUNDER) && is_real_founder(user, ci)) || (!(ci->flags & CI_SECUREFOUNDER) && is_founder(user, ci))) { - send_cmd(whosends(ci), "MODE %s +oq %s %s", chan, user->nick, - user->nick); + send_mode(whosends(ci), chan, "+oq %s %s", user->nick, user->nick); return 1; } @@ -1648,8 +1640,7 @@ int check_should_protect(User * user, const char *chan) return 0; if (check_access(user, ci, CA_AUTOPROTECT)) { - send_cmd(whosends(ci), "MODE %s +oa %s %s", chan, user->nick, - user->nick); + send_mode(whosends(ci), chan, "+oa %s %s", user->nick, user->nick); return 1; } @@ -1796,7 +1787,7 @@ int check_kick(User * user, char *chan) free(av[1]); } - send_cmd(whosends(ci), "MODE %s +b %s %lu", chan, mask, time(NULL)); + send_mode(whosends(ci), chan, "+b %s %lu", mask, time(NULL)); send_cmd(whosends(ci), "KICK %s %s :%s", chan, user->nick, reason); return 1; @@ -1850,7 +1841,7 @@ void restore_topic(const char *chan) #ifdef IRC_HYBRID if (whosends(ci) == s_ChanServ) { send_cmd(NULL, "SJOIN %ld %s + :%s", time(NULL), chan, s_ChanServ); - send_cmd(NULL, "MODE %s +o %s", chan, s_ChanServ); + send_mode(NULL, chan, "+o %s", s_ChanServ); } send_cmd(whosends(ci), "TOPIC %s :%s", chan, c->topic ? c->topic : ""); if (whosends(ci) == s_ChanServ) { @@ -1893,7 +1884,7 @@ int check_topiclock(Channel * c, time_t topic_time) if (whosends(ci) == s_ChanServ) { send_cmd(NULL, "SJOIN %ld %s + :%s", time(NULL), c->name, s_ChanServ); - send_cmd(NULL, "MODE %s +o %s", c->name, s_ChanServ); + send_mode(NULL, c->name, "+o %s", s_ChanServ); } send_cmd(whosends(ci), "TOPIC %s :%s", c->name, c->topic ? c->topic : ""); @@ -1973,7 +1964,7 @@ void cs_remove_nick(const NickCore * nc) /* Maybe move this to delchan() ? */ if ((ci->c) && (ci->c->mode & CMODE_r)) { ci->c->mode &= ~CMODE_r; - send_cmd(whosends(ci), "MODE %s -r", ci->name); + send_mode(whosends(ci), ci->name, "-r"); } #endif @@ -2729,7 +2720,7 @@ static int do_register(User * u) /* Implement new mode lock */ check_modes(c); #if defined(IRC_ULTIMATE3) || defined(IRC_RAGE2) - send_cmd(s_ChanServ, "MODE %s +a %s", chan, u->nick); + send_mode(s_ChanServ, chan, "+a %s", u->nick); #endif } return MOD_CONT; @@ -2856,7 +2847,7 @@ static int do_drop(User * u) #ifndef IRC_HYBRID if (ci->c) { ci->c->mode &= ~CMODE_r; - send_cmd(whosends(ci), "MODE %s -r", ci->name); + send_mode(whosends(ci), ci->name, "-r"); } #endif alog("%s: Channel %s dropped by %s!%s@%s (founder: %s)", @@ -4228,7 +4219,7 @@ void stick_mask(ChannelInfo * ci, AutoKick * akick) av[0] = sstrdup("+b"); av[1] = akick->u.mask; - send_cmd(whosends(ci), "MODE %s +b %s", ci->c->name, akick->u.mask); + send_mode(whosends(ci), ci->c->name, "+b %s", akick->u.mask); chan_set_modes(s_ChanServ, ci->c, 2, av, 1); free(av[0]); } @@ -4248,8 +4239,7 @@ void stick_all(ChannelInfo * ci) av[0] = sstrdup("+b"); av[1] = akick->u.mask; - send_cmd(whosends(ci), "MODE %s +b %s", ci->c->name, - akick->u.mask); + send_mode(whosends(ci), ci->c->name, "+b %s", akick->u.mask); chan_set_modes(s_ChanServ, ci->c, 2, av, 1); free(av[0]); } @@ -5195,8 +5185,8 @@ static int do_util(User * u, CSModeUtil * util) for (uc = u->chans; uc; uc = uc->next) { if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN) && check_access(u, ci, util->levelself)) { - send_cmd(whosends(ci), "MODE %s %s %s", uc->chan->name, - util->mode, u->nick); + send_mode(whosends(ci), uc->chan->name, "%s %s", + util->mode, u->nick); chan_set_modes(s_ChanServ, uc->chan, 2, av, 1); if (util->notice && ci->flags & util->notice) @@ -5234,8 +5224,7 @@ static int do_util(User * u, CSModeUtil * util) notice_lang(s_ChanServ, u, PERMISSION_DENIED); #endif } else { - send_cmd(whosends(ci), "MODE %s %s %s", c->name, util->mode, - u2->nick); + send_mode(whosends(ci), c->name, "%s %s", util->mode, u2->nick); av[0] = util->mode; av[1] = u2->nick; @@ -5335,8 +5324,8 @@ static int do_owner(User * u) for (uc = u->chans; uc; uc = uc->next) { if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN) && is_founder(u, ci)) { - send_cmd(whosends(ci), "MODE %s %s %s", uc->chan->name, - av[0], u->nick); + send_mode(whosends(ci), uc->chan->name, "%s %s", + av[0], u->nick); chan_set_modes(s_ChanServ, uc->chan, 2, av, 1); } } @@ -5356,7 +5345,7 @@ static int do_owner(User * u) } else if (!is_founder(u, ci)) { notice_lang(s_ChanServ, u, ACCESS_DENIED); } else { - send_cmd(whosends(ci), "MODE %s +q %s", c->name, u->nick); + send_mode(whosends(ci), c->name, "+q %s", u->nick); av[0] = sstrdup("+q"); av[1] = u->nick; @@ -5387,8 +5376,8 @@ static int do_deowner(User * u) for (uc = u->chans; uc; uc = uc->next) { if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN) && is_founder(u, ci)) { - send_cmd(whosends(ci), "MODE %s %s %s", uc->chan->name, - av[0], u->nick); + send_mode(whosends(ci), uc->chan->name, "%s %s", + av[0], u->nick); chan_set_modes(s_ChanServ, uc->chan, 2, av, 1); } } @@ -5408,7 +5397,7 @@ static int do_deowner(User * u) } else if (!is_founder(u, ci)) { notice_lang(s_ChanServ, u, ACCESS_DENIED); } else { - send_cmd(whosends(ci), "MODE %s -q %s", c->name, u->nick); + send_mode(whosends(ci), c->name, "-q %s", u->nick); av[0] = sstrdup("-q"); av[1] = u->nick; @@ -5559,8 +5548,7 @@ static int do_ban(User * u) av[0] = sstrdup("+b"); get_idealban(ci, u, mask, sizeof(mask)); av[1] = mask; - send_cmd(whosends(ci), "MODE %s +b %s", uc->chan->name, - av[1]); + send_mode(whosends(ci), uc->chan->name, "+b %s", av[1]); chan_set_modes(s_ChanServ, uc->chan, 2, av, 1); free(av[0]); @@ -5615,7 +5603,7 @@ static int do_ban(User * u) av[0] = sstrdup("+b"); get_idealban(ci, u2, mask, sizeof(mask)); av[1] = mask; - send_cmd(whosends(ci), "MODE %s +b %s", c->name, av[1]); + send_mode(whosends(ci), c->name, "+b %s", av[1]); chan_set_modes(s_ChanServ, c, 2, av, 1); free(av[0]); @@ -5683,7 +5671,7 @@ static int do_cs_topic(User * u) if (whosends(ci) == s_ChanServ) { send_cmd(NULL, "SJOIN %ld %s + :%s", time(NULL), c->name, s_ChanServ); - send_cmd(NULL, "MODE %s +o %s", c->name, s_ChanServ); + send_mode(NULL, c->name, "+o %s", s_ChanServ); } send_cmd(whosends(ci), "TOPIC %s :%s", c->name, c->topic ? c->topic : ""); @@ -5729,7 +5717,7 @@ static int do_unban(User * u) av[1] = sstrdup("-b"); for (i = 0; i < count; i++) { if (match_usermask(bans[i], u)) { - send_cmd(whosends(ci), "MODE %s -b %s", chan, bans[i]); + send_mode(whosends(ci), chan, "-b %s", bans[i]); av[2] = sstrdup(bans[i]); do_cmode(s_ChanServ, 3, av); free(av[2]); @@ -5778,7 +5766,7 @@ static int do_clear(User * u) av[0] = sstrdup(chan); av[1] = sstrdup("-b"); av[2] = bans[i]; - send_cmd(whosends(ci), "MODE %s %s :%s", av[0], av[1], av[2]); + send_mode(whosends(ci), av[0], "%s :%s", av[1], av[2]); do_cmode(s_ChanServ, 3, av); free(av[2]); free(av[1]); @@ -5801,7 +5789,7 @@ static int do_clear(User * u) av[0] = sstrdup(chan); av[1] = sstrdup("-e"); av[2] = excepts[i]; - send_cmd(whosends(ci), "MODE %s %s :%s", av[0], av[1], av[2]); + send_mode(whosends(ci), av[0], "%s :%s", av[1], av[2]); do_cmode(s_ChanServ, 3, av); free(av[2]); free(av[1]); @@ -5816,8 +5804,8 @@ static int do_clear(User * u) if (c->mode) { /* Clear modes */ - send_cmd(s_ChanServ, "MODE %s %s %s", c->name, MODESTOREMOVE, - c->key ? c->key : ""); + send_mode(s_ChanServ, c->name, "%s %s", MODESTOREMOVE, + c->key ? c->key : ""); argv[0] = sstrdup(MODESTOREMOVE); argv[1] = c->key ? c->key : NULL; chan_set_modes(s_OperServ, c, c->key ? 2 : 1, argv, 0); @@ -5857,7 +5845,7 @@ static int do_clear(User * u) *end = 0; - send_cmd(whosends(ci), "MODE %s -%s", c->name, buf); + send_mode(whosends(ci), c->name, "-%s", buf); c->mode = 0; check_modes(c); } @@ -5873,7 +5861,7 @@ static int do_clear(User * u) av[0] = sstrdup(chan); av[1] = sstrdup("-o"); av[2] = sstrdup(cu->user->nick); - send_cmd(whosends(ci), "MODE %s %s :%s", av[0], av[1], av[2]); + send_mode(whosends(ci), av[0], "%s :%s", av[1], av[2]); do_cmode(s_ChanServ, 3, av); free(av[2]); free(av[1]); @@ -5892,7 +5880,7 @@ static int do_clear(User * u) av[0] = sstrdup(chan); av[1] = sstrdup("-h"); av[2] = sstrdup(cu->user->nick); - send_cmd(whosends(ci), "MODE %s %s :%s", av[0], av[1], av[2]); + send_mode(whosends(ci), av[0], "%s :%s", av[1], av[2]); do_cmode(s_ChanServ, 3, av); free(av[2]); free(av[1]); @@ -5911,7 +5899,7 @@ static int do_clear(User * u) av[0] = sstrdup(chan); av[1] = sstrdup("-v"); av[2] = sstrdup(cu->user->nick); - send_cmd(whosends(ci), "MODE %s %s :%s", av[0], av[1], av[2]); + send_mode(whosends(ci), av[0], "%s :%s", av[1], av[2]); do_cmode(s_ChanServ, 3, av); free(av[2]); free(av[1]); @@ -116,6 +116,7 @@ int UsePrivmsg; int DumpCore; int LogUsers; int NickRegDelay; +int UseSVSHOLD; int UseMail; char *SendMailPath; @@ -611,6 +612,7 @@ Directive directives[] = { {"UpdateTimeout", {{PARAM_TIME, PARAM_RELOAD, &UpdateTimeout}}}, {"UseMail", {{PARAM_SET, PARAM_RELOAD, &UseMail}}}, {"UsePrivmsg", {{PARAM_SET, PARAM_RELOAD, &UsePrivmsg}}}, + {"UseSVSHOLD", {{PARAM_SET, PARAM_RELOAD, &UseSVSHOLD}}}, {"WallAkillExpire", {{PARAM_SET, PARAM_RELOAD, &WallAkillExpire}}}, {"WallBadOS", {{PARAM_SET, PARAM_RELOAD, &WallBadOS}}}, {"WallDrop", {{PARAM_SET, PARAM_RELOAD, &WallDrop}}}, diff --git a/data/example.conf b/data/example.conf index 201bf5274..8fadac2e0 100644 --- a/data/example.conf +++ b/data/example.conf @@ -235,12 +235,15 @@ HelpChannel "#help" # # If your network has a common domain name, specify it there (for # example, all IRCZONE servers have a name ending in ".irczone.cl", -# so "irczone.cl" would be set there. It will be used by the OperServ -# GLOBAL command, and if you don't have a common domain name, this -# command may just not work. +# so "irczone.cl" would be set there. # # You can specify more than one Network Domain by separating each one by # a space: NetworkDomain "localnet.net localnet.com" +# +# Note that this directive is no longer used by the GLOBAL command, since +# it uses a dynamic list of connected servers regardless of their +# domains. However, some modules may still use this value, so you might +# want to keep it just in case. NetworkDomain "localnet.com" @@ -437,6 +440,14 @@ GlobalOnCycleUP "Services are now back online - have a nice day" # connected for at least X seconds. #NickRegDelay 30 +# UseSVSHOLD [OPTIONAL] +# Allows Bahamut-networks to use SVSHOLD instead of the services +# enforcer. This option has been introduced in Bahamut 1.4.35 and +# places a temporary Q:Line instead of introducing a new nick, +# which is better for both CPU and bandwidth. If you enable this +# option on a pre-1.4.35 Bahamut, it is most likely to break. +#UseSVSHOLD + ########################################################################### # # Mail-related options diff --git a/docs/README b/docs/README index 22c1db10c..c1aab6e3f 100644 --- a/docs/README +++ b/docs/README @@ -61,11 +61,12 @@ Anope credits: JH <jh@irc-chat.net> Joris Vink <joris@anope.org> Lucas Nussbaum <lucas@lucas-nussbaum.net> + Pieter Bootsma <geniusdex@anope.org> Thomas Juberg Stensås <ShadowMaster@Shadow-Realm.org> Trystan .S Lee <trystan@anope.org> openglx <openglx@brasnerd.com.br> Anope Translations: - GeniousDex (nl.l) + GeniusDex (nl.l) Oleg Nikolaev aka Isot <isot@complife.ru> (ru.l) Stuff <the.stuff@gmx.de> (de.l) DrStein (es.l) @@ -123,7 +124,7 @@ Currently available services are: Anope currently works with: - DreamForge 4.6.7 - - Bahamut 1.4.27 or later + - Bahamut 1.4.35 or later - UnrealIRCd 3.1.1 or later (including 3.2) - UltimateIRCd 2.8.2 or later (including 3.0.0) - ViagraIRCd 1.3 or later @@ -279,6 +279,7 @@ E int UsePrivmsg; E int DumpCore; E int LogUsers; E int NickRegDelay; +E int UseSVSHOLD; E char **HostSetters; E int HostNumber; @@ -773,6 +774,8 @@ E void wallops(const char *source, const char *fmt, ...) E void notice(const char *source, const char *dest, const char *fmt, ...) FORMAT(printf,3,4); +E void notice_server(const char *source, Server * s, const char *fmt, ...) + FORMAT(printf,3,4); E void notice_user(const char *source, User *u, const char *fmt, ...) FORMAT(printf,3,4); @@ -783,6 +786,28 @@ E void notice_help(const char *source, User *dest, int message, ...); E void privmsg(const char *source, const char *dest, const char *fmt, ...) FORMAT(printf,3,4); +E void send_mode(const char *source, const char *on, const char *fmt, ...) + FORMAT(printf,3,4); + +/**** servers.c ****/ + +E Server *servlist; +E Server *me_server; +#ifdef IRC_BAHAMUT +E uint16 uplink_capab; +#endif + +E Server *first_server(int flags); +E Server *next_server(int flags); + +E Server *new_server(Server *uplink, const char *name, const char *desc, + uint16 flags); + +E Server *findserver(Server *s, const char *name); + +E void do_server(const char *source, int ac, char **av); +E void do_squit(const char *source, int ac, char **av); + /**** sessions.c ****/ E Exception *exceptions; @@ -825,6 +850,8 @@ E time_t maxusertime; E void set_umode(User * user, int ac, char **av); +E void delete_user(User *user); + E void get_user_stats(long *nusers, long *memuse); E User *finduser(const char *nick); E User *firstuser(void); @@ -63,7 +63,7 @@ extern void moduleAddMsgs(void); do { \ send_cmd(NULL, "NICK %s 1 %ld %s %s %s 0 :%s", (nick), time(NULL), \ ServiceUser, ServiceHost, ServerName, (name)); \ - if (strcmp(modes, "+")) send_cmd((nick), "MODE %s %s", (nick), (modes)); \ + if (strcmp(modes, "+")) send_mode((nick), (nick), "%s", (modes)); \ send_cmd(NULL, "SQLINE %s :Reserved for services", (nick)); \ } while (0) #elif defined(IRC_PTLINK) @@ -705,6 +705,9 @@ int init(int ac, char **av) alog("Info: Not reflecting database records."); } #endif + /* Make myself known to myself in the serverlist */ + me_server = new_server(NULL, ServerName, ServerDesc, SERVER_ISME); + /* Connect to the remote server */ servsock = conn(RemoteServer, RemotePort, LocalHost, LocalPort); if (servsock < 0 && RemoteServer2) { @@ -762,7 +765,7 @@ int init(int ac, char **av) send_cmd(NULL, "PASS %s :TS", RemotePassword2); else if (servernum == 3) send_cmd(NULL, "PASS %s :TS", RemotePassword3); - send_cmd(NULL, "CAPAB NICKIP SSJOIN TS3"); + send_cmd(NULL, "CAPAB NICKIP SSJOIN TS3 NOQUIT TSMODE UNCONNECT"); #elif defined(IRC_HYBRID) if (servernum == 1) send_cmd(NULL, "PASS %s :TS", RemotePassword); diff --git a/messages.c b/messages.c index 571bf6286..12804e036 100644 --- a/messages.c +++ b/messages.c @@ -58,6 +58,28 @@ static int m_away(char *source, int ac, char **av) #ifdef IRC_BAHAMUT +static int m_capab(char *source, int ac, char **av) +{ + int i; + + for (i = 0; i < ac; i++) { + if (!stricmp(av[i], "NOQUIT")) + uplink_capab |= CAPAB_NOQUIT; + else if (!stricmp(av[i], "TSMODE")) + uplink_capab |= CAPAB_TSMODE; + else if (!stricmp(av[i], "UNCONNECT")) + uplink_capab |= CAPAB_UNCONNECT; + } + + return MOD_CONT; +} + +#endif + +/*************************************************************************/ + +#ifdef IRC_BAHAMUT + static int m_cs(char *source, int ac, char **av) { User *u; @@ -675,10 +697,23 @@ static int m_quit(char *source, int ac, char **av) /*************************************************************************/ +static int m_squit(char *source, int ac, char **av) +{ + if (ac != 2) + return MOD_CONT; + do_squit(source, ac, av); + return MOD_CONT; +} + +/*************************************************************************/ + static int m_server(char *source, int ac, char **av) { if (!stricmp(av[1], "1")) uplink = sstrdup(av[0]); + if (ac != 3) + return MOD_CONT; + do_server(source, ac, av); return MOD_CONT; } @@ -1126,7 +1161,7 @@ void moduleAddMsgs(void) { m = createMessage("PRIVMSG", m_privmsg); addCoreMessage(IRCD,m); m = createMessage("QUIT", m_quit); addCoreMessage(IRCD,m); m = createMessage("SERVER", m_server); addCoreMessage(IRCD,m); - m = createMessage("SQUIT", NULL); addCoreMessage(IRCD,m); + m = createMessage("SQUIT", m_squit); addCoreMessage(IRCD,m); m = createMessage("STATS", m_stats); addCoreMessage(IRCD,m); m = createMessage("TIME", m_time); addCoreMessage(IRCD,m); m = createMessage("TOPIC", m_topic); addCoreMessage(IRCD,m); @@ -1156,7 +1191,7 @@ void moduleAddMsgs(void) { /* Bahamut specific messages */ #ifdef IRC_BAHAMUT - m = createMessage("CAPAB", NULL); addCoreMessage(IRCD,m); + m = createMessage("CAPAB", m_capab); addCoreMessage(IRCD,m); m = createMessage("CS", m_cs); addCoreMessage(IRCD,m); m = createMessage("HS", m_hs); addCoreMessage(IRCD,m); m = createMessage("MS", m_ms); addCoreMessage(IRCD,m); diff --git a/nickserv.c b/nickserv.c index c8c7546c6..5916d319f 100644 --- a/nickserv.c +++ b/nickserv.c @@ -1112,14 +1112,22 @@ void cancel_user(User * u) if (na) { if (na->status & NS_GUESTED) { - NEWNICK(u->nick, NSEnforcerUser, NSEnforcerHost, - "Services Enforcer", "+", 0); - add_ns_timeout(na, TO_RELEASE, NSReleaseTimeout); - na->status &= ~NS_TEMPORARY; +#ifdef HAS_SVSHOLD + if (UseSVSHOLD) { + send_cmd(ServerName, "SVSHOLD %s %d :%s", na->nick, + NSReleaseTimeout, + "Being held for registered user"); + } else { +#endif + NEWNICK(u->nick, NSEnforcerUser, NSEnforcerHost, + "Services Enforcer", "+", 0); + add_ns_timeout(na, TO_RELEASE, NSReleaseTimeout); +#ifdef HAS_SVSHOLD + } +#endif na->status |= NS_KILL_HELD; - } else { - na->status &= ~NS_TEMPORARY; } + na->status &= ~NS_TEMPORARY; del_ns_timeout(na, TO_COLLIDE); } @@ -1685,7 +1693,12 @@ static void release(NickAlias * na, int from_timeout) { if (!from_timeout) del_ns_timeout(na, TO_RELEASE); - send_cmd(na->nick, "QUIT"); +#ifdef HAS_SVSHOLD + if (UseSVSHOLD) + send_cmd(ServerName, "SVSHOLD %s 0", na->nick); + else +#endif + send_cmd(na->nick, "QUIT"); na->status &= ~NS_KILL_HELD; } diff --git a/operserv.c b/operserv.c index 1aba50016..a21d5dc15 100644 --- a/operserv.c +++ b/operserv.c @@ -1023,67 +1023,20 @@ void oper_global(char *nick, char *fmt, ...) { va_list args; char msg[2048]; /* largest valid message is 512, this should cover any global */ - int i; + Server *s; va_start(args, fmt); vsnprintf(msg, sizeof(msg), fmt, args); va_end(args); -#ifdef IRC_HYBRID - if (DomainNumber > 0) { - for (i = 0; i < DomainNumber; i++) { - if ((nick) && (!AnonymousGlobal)) { - send_cmd(s_GlobalNoticer, "NOTICE $$*.%s :[%s] %s", - NetworkDomains[i], nick, msg); - } else { - send_cmd(s_GlobalNoticer, "NOTICE $$*.%s :%s", - NetworkDomains[i], msg); - } - } - } else { - /* Go through all common top-level domains. If you have others, - * add them here. - */ - if ((nick) && (!AnonymousGlobal)) { - notice(s_GlobalNoticer, "$$*.com", "[%s] %s", nick, msg); - notice(s_GlobalNoticer, "$$*.net", "[%s] %s", nick, msg); - notice(s_GlobalNoticer, "$$*.org", "[%s] %s", nick, msg); - notice(s_GlobalNoticer, "$$*.edu", "[%s] %s", nick, msg); - } else { - notice(s_GlobalNoticer, "$$*.com", "%s", msg); - notice(s_GlobalNoticer, "$$*.net", "%s", msg); - notice(s_GlobalNoticer, "$$*.org", "%s", msg); - notice(s_GlobalNoticer, "$$*.edu", "%s", msg); - } - } -#else - if (DomainNumber > 0) { - for (i = 0; i < DomainNumber; i++) { - if ((nick) && (!AnonymousGlobal)) { - send_cmd(s_GlobalNoticer, "NOTICE $*.%s :[%s] %s", - NetworkDomains[i], nick, msg); - } else { - send_cmd(s_GlobalNoticer, "NOTICE $*.%s :%s", - NetworkDomains[i], msg); - } - } - } else { - /* Go through all common top-level domains. If you have others, - * add them here. - */ - if ((nick) && (!AnonymousGlobal)) { - notice(s_GlobalNoticer, "$*.com", "[%s] %s", nick, msg); - notice(s_GlobalNoticer, "$*.net", "[%s] %s", nick, msg); - notice(s_GlobalNoticer, "$*.org", "[%s] %s", nick, msg); - notice(s_GlobalNoticer, "$*.edu", "[%s] %s", nick, msg); - } else { - notice(s_GlobalNoticer, "$*.com", "%s", msg); - notice(s_GlobalNoticer, "$*.net", "%s", msg); - notice(s_GlobalNoticer, "$*.org", "%s", msg); - notice(s_GlobalNoticer, "$*.edu", "%s", msg); - } + s = first_server(0); + while (s) { + if ((nick) && (!AnonymousGlobal)) + notice_server(s_GlobalNoticer, s, "[%s] %s", nick, msg); + else + notice_server(s_GlobalNoticer, s, "%s", msg); + s = next_server(0); } -#endif } /*************************************************************************/ @@ -1476,7 +1429,7 @@ static int do_os_mode(User * u) return MOD_CONT; #endif } else { - send_cmd(s_OperServ, "MODE %s %s", chan, modes); + send_mode(s_OperServ, chan, "%s", modes); ac = split_buf(modes, &av, 1); chan_set_modes(s_OperServ, c, ac, av, 0); @@ -1527,7 +1480,7 @@ static int do_operumodes(User * u) if (!(u2 = finduser(nick))) { notice_lang(s_OperServ, u, NICK_X_NOT_IN_USE, nick); } else { - send_cmd(s_OperServ, "MODE %s %s", nick, modes); + send_mode(s_OperServ, nick, "%s", modes); change_user_mode(u2, modes, NULL); @@ -1575,7 +1528,7 @@ static int do_operoline(User * u) notice_lang(s_OperServ, u, NICK_X_NOT_IN_USE, nick); } else if (u2 && flags[0] == '+') { send_cmd(s_OperServ, "SVSO %s %s", nick, flags); - send_cmd(s_OperServ, "MODE %s +o", nick); + send_mode(s_OperServ, nick, "+o"); change_user_mode(u2, "+o", NULL); notice_lang(s_OperServ, u2, OPER_OLINE_IRCOP); notice_lang(s_OperServ, u, OPER_OLINE_SUCCESS, flags, nick); @@ -1644,8 +1597,7 @@ static int do_clearmodes(User * u) argv[0] = sstrdup("-o"); argv[1] = cu->user->nick; - send_cmd(s_OperServ, "MODE %s -o %s", c->name, - cu->user->nick); + send_mode(s_OperServ, c->name, "-o %s", cu->user->nick); chan_set_modes(s_OperServ, c, 2, argv, 0); free(argv[0]); @@ -1661,8 +1613,7 @@ static int do_clearmodes(User * u) argv[0] = sstrdup("-v"); argv[1] = sstrdup(cu->user->nick); - send_cmd(s_OperServ, "MODE %s -v %s", c->name, - cu->user->nick); + send_mode(s_OperServ, c->name, "-v %s", cu->user->nick); chan_set_modes(s_OperServ, c, 2, argv, 0); free(argv[0]); @@ -1678,8 +1629,7 @@ static int do_clearmodes(User * u) argv[0] = sstrdup("-h"); argv[1] = sstrdup(cu->user->nick); - send_cmd(s_OperServ, "MODE %s -h %s", c->name, - cu->user->nick); + send_mode(s_OperServ, c->name, "-h %s", cu->user->nick); chan_set_modes(s_OperServ, c, 2, argv, 0); free(argv[0]); @@ -1688,8 +1638,8 @@ static int do_clearmodes(User * u) } /* Clear modes */ - send_cmd(s_OperServ, "MODE %s %s %s", c->name, MODESTOREMOVE, - c->key ? c->key : ""); + send_mode(s_OperServ, c->name, "%s %s", MODESTOREMOVE, + c->key ? c->key : ""); argv[0] = sstrdup(MODESTOREMOVE); argv[1] = c->key ? c->key : NULL; chan_set_modes(s_OperServ, c, c->key ? 2 : 1, argv, 0); @@ -1705,7 +1655,7 @@ static int do_clearmodes(User * u) for (i = 0; i < count; i++) { argv[0] = sstrdup("-b"); argv[1] = bans[i]; - send_cmd(s_OperServ, "MODE %s -b %s", c->name, argv[1]); + send_mode(s_OperServ, c->name, "-b %s", argv[1]); chan_set_modes(s_OperServ, c, 2, argv, 0); free(argv[1]); free(argv[0]); @@ -1724,7 +1674,7 @@ static int do_clearmodes(User * u) for (i = 0; i < exceptcount; i++) { argv[0] = sstrdup("-e"); argv[1] = excepts[i]; - send_cmd(s_OperServ, "MODE %s -e %s", c->name, argv[1]); + send_mode(s_OperServ, c->name, "-e %s", argv[1]); chan_set_modes(s_OperServ, c, 2, argv, 0); free(argv[1]); free(argv[0]); @@ -4448,8 +4398,8 @@ static int do_noop(User * u) /* Kill all the IRCops of the server */ for (u2 = firstuser(); u2; u2 = u3) { u3 = nextuser(); - if ((u2) && is_oper(u2) && (u2->server) - && !stricmp(u2->server, server)) { + if ((u2) && is_oper(u2) && (u2->server->name) + && !stricmp(u2->server->name, server)) { kill_user(s_OperServ, u2->nick, reason); } } @@ -4486,6 +4436,7 @@ static int do_jupe(User * u) #else send_cmd(NULL, "SERVER %s 2 :%s", jserver, rbuf); #endif + new_server(me_server, jserver, rbuf, SERVER_JUPED); if (WallOSJupe) wallops(s_OperServ, "\2%s\2 used JUPE on \2%s\2", u->nick, @@ -80,6 +80,25 @@ void notice(const char *source, const char *dest, const char *fmt, ...) /*************************************************************************/ +void notice_server(const char *source, Server * s, const char *fmt, ...) +{ + va_list args; + char buf[BUFSIZE]; + + va_start(args, fmt); + + vsnprintf(buf, sizeof(buf), fmt, args); +#ifdef IRC_HYBRID + send_cmd(source, "%s $$%s :%s", (UsePrivmsg ? "PRIVMSG" : "NOTICE"), + s->name, buf); +#else + send_cmd(source, "%s $%s :%s", (UsePrivmsg ? "PRIVMSG" : "NOTICE"), + s->name, buf); +#endif +} + +/*************************************************************************/ + void notice_user(const char *source, User * u, const char *fmt, ...) { va_list args; @@ -200,3 +219,22 @@ void privmsg(const char *source, const char *dest, const char *fmt, ...) } /*************************************************************************/ + +/* Sends a MODE from the given source on the given nick */ +void send_mode(const char *source, const char *on, const char *fmt, ...) +{ + va_list args; + char buf[BUFSIZE]; + + va_start(args, fmt); + + vsnprintf(buf, sizeof(buf), fmt, args); +#ifdef IRC_BAHAMUT + if (uplink_capab & CAPAB_TSMODE) + send_cmd(source, "MODE %s 0 %s", on, buf); + else +#endif + send_cmd(source, "MODE %s %s", on, buf); +} + +/*************************************************************************/ diff --git a/servers.c b/servers.c new file mode 100644 index 000000000..71e6ce92a --- /dev/null +++ b/servers.c @@ -0,0 +1,259 @@ +/* Routines to maintain a list of connected servers + * + * (C) 2004 Anope Team / GeniusDex + * Contact us at info@anope.org + * + * Please read COPYING and README for furhter details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ + +#include "services.h" + +Server *servlist = NULL; +Server *me_server = NULL; +#ifdef IRC_BAHAMUT +uint16 uplink_capab; +#endif + +/* For first_server / next_server */ +static Server *server_cur; + +/*************************************************************************/ + +/* Walk through the servers list */ +Server *first_server(int flags) +{ + server_cur = servlist; + if (flags > -1) { + while (server_cur && (server_cur->flags != flags)) + server_cur = next_server(flags); + } + return server_cur; +} + +Server *next_server(int flags) +{ + if (!server_cur) + return NULL; + + do { + if (server_cur->links) { + server_cur = server_cur->links; + } else if (server_cur->next) { + server_cur = server_cur->next; + } else { + do { + server_cur = server_cur->uplink; + if (server_cur && server_cur->next) { + server_cur = server_cur->next; + break; + } + } while (server_cur); + } + } while (server_cur && ((flags > -1) || (server_cur->flags != flags))); + + return server_cur; +} + +/*************************************************************************/ + +/* This function makes a new Server structure and links it in the right + * places in the linked list if a Server struct to it's uplink if provided. + * It can also be NULL to indicate it's the uplink and should be first in + * the server list. + */ + +Server *new_server(Server * uplink, const char *name, const char *desc, + uint16 flags) +{ + Server *serv; + + serv = scalloc(sizeof(Server), 1); + if (!name) + name = ""; + serv->name = sstrdup(name); + serv->desc = sstrdup(desc); + serv->flags = flags; + serv->uplink = uplink; + serv->links = NULL; + serv->prev = NULL; + + if (!uplink) { + serv->hops = 0; + serv->next = servlist; + if (servlist) + servlist->prev = serv; + servlist = serv; + } else { + serv->hops = uplink->hops + 1; + serv->next = uplink->links; + if (uplink->links) + uplink->links->prev = serv; + uplink->links = serv; + } + + return serv; +} + +/*************************************************************************/ + +/* Remove and free a Server structure. This function is the most complete + * remove treatment a server can get, as it first quits all clients which + * still pretend to be on this server, then it walks through all connected + * servers and disconnects them too. If all mess is cleared, the server + * itself will be too. + */ + +static void delete_server(Server * serv, const char *quitreason) +{ + Server *s, *snext; +#ifdef IRC_BAHAMUT + User *u, *unext; + NickAlias *na; +#endif + + if (!serv) { + alog("delete_server() called with NULL arg!"); + return; + } + + if (debug) + alog("delete_server() called for %s", serv->name); + +#ifdef IRC_BAHAMUT + if (uplink_capab & CAPAB_NOQUIT) { + u = firstuser(); + while (u) { + unext = nextuser(); + if (u->server == serv) { + if ((na = u->na) && !(na->status & NS_VERBOTEN) + && (na->status & (NS_IDENTIFIED | NS_RECOGNIZED))) { + na->last_seen = time(NULL); + if (na->last_quit) + free(na->last_quit); + na->last_quit = + (quitreason ? sstrdup(quitreason) : NULL); + } +#ifndef STREAMLINED + if (LimitSessions) + del_session(u->host); +#endif + delete_user(u); + } + u = unext; + } + if (debug >= 2) + alog("delete_server() cleared all users"); + } +#endif + + s = serv->links; + while (s) { + snext = s->next; + delete_server(s, quitreason); + s = snext; + } + + if (debug >= 2) + alog("delete_server() cleared all servers"); + + free(serv->name); + free(serv->desc); + if (serv->prev) + serv->prev->next = serv->next; + if (serv->next) + serv->next->prev = serv->prev; + if (serv->uplink->links == serv) + serv->uplink->links = serv->next; + + if (debug) + alog("delete_server() completed"); +} + +/*************************************************************************/ + +/* Find a server by name, returns NULL if not found */ + +Server *findserver(Server * s, const char *name) +{ + Server *sl; + + if (debug >= 3) + alog("debug: findserver(%p)", name); + while (s && (stricmp(s->name, name) != 0)) { + if (s->links) { + sl = findserver(s->links, name); + if (sl) + s = sl; + else + s = s->next; + } else { + s = s->next; + } + } + if (debug >= 3) + alog("debug: findserver(%s) -> %p", name, s); + return s; +} + +/*************************************************************************/ +/* :<introducing server> SERVER <servername> <hops> :<description> + */ +void do_server(const char *source, int ac, char **av) +{ + Server *s; + + if (debug) + alog("debug: Server introduced (%s) from %s", av[0], source); + + if (source[0] == '\0') + s = me_server; + else + s = findserver(servlist, source); +#ifdef IRC_PTLINK + if (ac < 4) + alog("Malformed SERVER received (less than 4 params)"); + else + new_server(s, av[0], av[3], 0); +#else + if (ac < 3) + alog("Malformed SERVER received (less than 3 params)"); + else + new_server(s, av[0], av[2], 0); +#endif +} + +/*************************************************************************/ +/* SQUIT <server> :<comment> + */ +void do_squit(const char *source, int ac, char **av) +{ + char buf[BUFSIZE]; + Server *s; + + s = findserver(servlist, av[0]); + if (!s) { + alog("SQUIT for nonexistent server (%s)!!", av[0]); + return; + } + + snprintf(buf, sizeof(buf), "%s %s", s->name, + (s->uplink ? s->uplink->name : "")); + +#ifdef IRC_BAHAMUT + if ((s->uplink == me_server) && (uplink_capab & CAPAB_UNCONNECT)) { + if (debug) + alog("debuf: Sending UNCONNECT SQUIT for %s", s->name); + send_cmd(ServerName, "SQUIT %s :%s", s->name, buf); + } +#endif + + delete_server(s, buf); +} + +/* EOF */ diff --git a/services.h b/services.h index c285b13a5..6033673a0 100644 --- a/services.h +++ b/services.h @@ -125,6 +125,7 @@ extern int toupper(char), tolower(char); /*************************************************************************/ +typedef struct server_ Server; typedef struct user_ User; typedef struct channel_ Channel; @@ -185,6 +186,8 @@ typedef struct channel_ Channel; #ifdef IRC_BAHAMUT # define HAS_NICKIP +# define HAS_EXCEPT +# define HAS_SVSHOLD # define NICKSERV_MODE "+o" # define CHANSERV_MODE "+o" # define MEMOSERV_MODE "+o" @@ -903,6 +906,32 @@ struct csmodeutil_ { #endif /*************************************************************************/ +/* Server CAPAB flags */ +#ifdef IRC_BAHAMUT +# define CAPAB_NOQUIT 0x0001 +# define CAPAB_TSMODE 0x0002 +# define CAPAB_UNCONNECT 0x0004 +#endif + +/* Server data */ + +struct server_ { + Server *next, *prev; + + char *name; /* Server name */ + uint16 hops; /* Hops between services and server */ + char *desc; /* Server description */ + uint16 flags; /* Some info flags, as defined below */ + + Server *links; /* Linked list head for linked servers */ + Server *uplink; /* Server which pretends to be the uplink */ +}; + +#define SERVER_ISME 0x0001 +#define SERVER_JUPED 0x0002 + +/*************************************************************************/ + /* Online user and channel data. */ struct user_ { User *next, *prev; @@ -918,7 +947,7 @@ struct user_ { char *vident; /* User's virtual ident */ #endif char *realname; - char *server; /* Name of server user is on */ + Server *server; /* Server user is connected to */ char *nickTrack; /* Nick Tracking */ @@ -256,6 +256,14 @@ void set_umode(User * user, int ac, char **av) case '-': add = 0; break; +#if defined(IRC_BAHAMUT) + case 'a': + if (add && !is_services_admin(user)) { + send_cmd(ServerName, "SVSMODE %s -a", user->nick); + user->mode &= ~UMODE_a; + } + break; +#endif #if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3) case 'a': if (add && !is_services_oper(user)) { @@ -362,7 +370,7 @@ void set_umode(User * user, int ac, char **av) /* Remove and free a User structure. */ -static void delete_user(User * user) +void delete_user(User * user) { struct u_chanlist *c, *c2; struct u_chaninfolist *ci, *ci2; @@ -372,11 +380,11 @@ static void delete_user(User * user) alog("LOGUSERS: %s (%s@%s => %s) (%s) left the network (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), user->realname, - user->server); + user->server->name); #else alog("LOGUSERS: %s (%s@%s) (%s) left the network (%s).", user->nick, user->username, user->host, - user->realname, user->server); + user->realname, user->server->name); #endif } @@ -394,7 +402,6 @@ static void delete_user(User * user) free(user->vhost); #endif free(user->realname); - free(user->server); if (debug >= 2) alog("debug: delete_user(): remove from channels"); c = user->chans; @@ -461,8 +468,8 @@ void get_user_stats(long *nusers, long *memuse) #endif if (user->realname) mem += strlen(user->realname) + 1; - if (user->server) - mem += strlen(user->server) + 1; + if (user->server->name) + mem += strlen(user->server->name) + 1; for (uc = user->chans; uc; uc = uc->next) mem += sizeof(*uc); for (uci = user->founder_chans; uci; uci = uci->next) @@ -687,7 +694,7 @@ User *do_nick(const char *source, char *nick, char *username, char *host, user = new_user(nick); user->username = sstrdup(username); user->host = sstrdup(host); - user->server = sstrdup(server); + user->server = findserver(servlist, server); user->realname = sstrdup(realname); user->timestamp = ts; user->my_signon = time(NULL); @@ -745,11 +752,11 @@ User *do_nick(const char *source, char *nick, char *username, char *host, if (LogUsers) { #ifdef HAS_VHOST - alog("LOGUSERS: %s (%s@%s => %s) (%s) changed his nick to %s (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), user->realname, nick, user->server); + alog("LOGUSERS: %s (%s@%s => %s) (%s) changed his nick to %s (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), user->realname, nick, user->server->name); #else alog("LOGUSERS: %s (%s@%s) (%s) changed his nick to %s (%s).", user->nick, user->username, user->host, - user->realname, nick, user->server); + user->realname, nick, user->server->name); #endif } @@ -862,6 +869,29 @@ User *do_nick(const char *source, char *nick, char *username, char *host, void do_umode(const char *source, int ac, char **av) { User *user; +#ifdef IRC_BAHAMUT + int i; + char *t; + + /* Another part of nice TSMODE support -GD */ + if (uplink_capab & CAPAB_TSMODE) { + for (i = 0; i < strlen(av[1]); i++) { + if (!isdigit(av[1][i])) + break; + } + if (av[1][i] == '\0') { + /* We have a valid TS field in av[1] now, so we can strip it off */ + /* But first we need to swap av[0] and av[1] -GD */ + t = av[0]; + av[0] = av[1]; + av[1] = t; + ac--; + av++; + } else { + alog("TSMODE enabled but MODE has no valid TS"); + } + } +#endif if (stricmp(source, av[0]) != 0) { alog("user: MODE %s %s from different nick %s!", av[0], av[1], diff --git a/version.log b/version.log index a853eb714..1bc085164 100644 --- a/version.log +++ b/version.log @@ -8,10 +8,15 @@ VERSION_MAJOR="1" VERSION_MINOR="7" VERSION_PATCH="4" -VERSION_BUILD="205" +VERSION_BUILD="206" # $Log$ # +# BUILD : 1.7.4 (206) +# BUGS : 55 +# NOTES : Added proper Bahamut1.8 support. Merged r132:195 from branch +# branches/proto/anope-bahamut18 which should now be obsolete. +# # BUILD : 1.7.4 (205) # BUGS : none # NOTES : SVN Framework. diff --git a/version.sh b/version.sh index d17cdab44..0797f2339 100644 --- a/version.sh +++ b/version.sh @@ -62,7 +62,7 @@ const char version_protocol[] = # define VER_IRCD "RageIRCd 2.0.* -" #elif defined(IRC_BAHAMUT) "Bahamut 1.4.27+" -# define VER_IRCD "BahamutIRCd 1.4.* -" +# define VER_IRCD "BahamutIRCd 1.4.*/1.8.* -" #elif defined(IRC_ULTIMATE) "UltimateIRCd 2.8.2+" # define VER_IRCD "UltimateIRCd 2.8.* -" |