From: wiebe Date: Wed, 17 Mar 2010 12:43:23 +0000 (+0100) Subject: Removed split.patch X-Git-Url: https://jfr.im/git/irc/quakenet/snircd-patchqueue.git/commitdiff_plain/6b09645d540540cdbdbdbd16fd86f8acd6ea8338 Removed split.patch --- diff --git a/series b/series index c967588..8d32add 100644 --- a/series +++ b/series @@ -34,5 +34,4 @@ oplevelforward.patch staffpriv.patch welcome.patch accountcollision.patch -split.patch match.patch diff --git a/split.patch b/split.patch deleted file mode 100644 index 4f9b180..0000000 --- a/split.patch +++ /dev/null @@ -1,1976 +0,0 @@ -work in progress -Add split functionality into ircd -Add /split command -Add /stats S/split (make /STATS s/S case sensitive, s spoofhosts) -Add feature SPLIT HIS_SPLIT -Add split.c split.h m_split.c -Add SPLIT priv -Add LS_JUPE for logging - -NOTE: feature SPLIT is default enabled as that is just easier when working on this patch. - -diff -r 1c62939e612b doc/api/log.txt ---- a/doc/api/log.txt Wed Feb 04 17:58:50 2009 +0100 -+++ b/doc/api/log.txt Wed Feb 04 18:04:57 2009 +0100 -@@ -41,7 +41,7 @@ - - - enum LogSys { -- LS_SYSTEM, LS_CONFIG, LS_OPERMODE, LS_GLINE, LS_JUPE, LS_WHO, LS_NETWORK, -+ LS_SYSTEM, LS_CONFIG, LS_OPERMODE, LS_GLINE, LS_JUPE, LS_SPLIT, LS_WHO, LS_NETWORK, - LS_OPERKILL, LS_SERVKILL, LS_USER, LS_OPER, LS_RESOLVER, LS_SOCKET, - LS_DEBUG, LS_OLDLOG, - LS_LAST_SYSTEM -diff -r 1c62939e612b include/client.h ---- a/include/client.h Wed Feb 04 17:58:50 2009 +0100 -+++ b/include/client.h Wed Feb 04 18:04:57 2009 +0100 -@@ -151,6 +151,7 @@ - PRIV_CHECK_CHANNEL, /* staff can /CHECK #channel */ - PRIV_WELCOME, /* oper can WELCOME */ - PRIV_LOCAL_WELCOME, /* oper can local WELCOME */ -+ PRIV_SPLIT, /* oper can SPLIT */ - PRIV_LAST_PRIV /**< number of privileges */ - }; - -diff -r 1c62939e612b include/handlers.h ---- a/include/handlers.h Wed Feb 04 17:58:50 2009 +0100 -+++ b/include/handlers.h Wed Feb 04 18:04:57 2009 +0100 -@@ -141,6 +141,7 @@ - extern int m_registered(struct Client*, struct Client*, int, char*[]); - extern int m_sethost(struct Client*, struct Client*, int, char*[]); - extern int m_silence(struct Client*, struct Client*, int, char*[]); -+extern int m_split(struct Client*, struct Client*, int, char*[]); - extern int m_staff(struct Client*, struct Client*, int, char*[]); - extern int m_stats(struct Client*, struct Client*, int, char*[]); - extern int m_time(struct Client*, struct Client*, int, char*[]); -@@ -182,6 +183,7 @@ - extern int mo_rping(struct Client*, struct Client*, int, char*[]); - extern int mo_set(struct Client*, struct Client*, int, char*[]); - extern int mo_settime(struct Client*, struct Client*, int, char*[]); -+extern int mo_split(struct Client*, struct Client*, int, char*[]); - extern int mo_squit(struct Client*, struct Client*, int, char*[]); - extern int mo_staff(struct Client*, struct Client*, int, char*[]); - extern int mo_stats(struct Client*, struct Client*, int, char*[]); -@@ -238,6 +240,7 @@ - extern int ms_sethost(struct Client*, struct Client*, int, char*[]); - extern int ms_settime(struct Client*, struct Client*, int, char*[]); - extern int ms_silence(struct Client*, struct Client*, int, char*[]); -+extern int ms_split(struct Client*, struct Client*, int, char*[]); - extern int ms_squit(struct Client*, struct Client*, int, char*[]); - extern int ms_staff(struct Client*, struct Client*, int, char*[]); - extern int ms_stats(struct Client*, struct Client*, int, char*[]); -diff -r 1c62939e612b include/ircd_features.h ---- a/include/ircd_features.h Wed Feb 04 17:58:50 2009 +0100 -+++ b/include/ircd_features.h Wed Feb 04 18:04:57 2009 +0100 -@@ -112,6 +112,10 @@ - FEAT_SETHOST_USER, - FEAT_SETHOST_AUTO, - -+ /* SPLIT */ -+ FEAT_SPLIT, -+ FEAT_SPLIT_AUTO_EXPIRE, -+ - /* HEAD_IN_SAND Features */ - FEAT_HIS_SNOTICES, - FEAT_HIS_SNOTICES_OPER_ONLY, -@@ -120,6 +124,7 @@ - FEAT_HIS_MAP, - FEAT_HIS_LINKS, - FEAT_HIS_TRACE, -+ FEAT_HIS_SPLIT, - FEAT_HIS_STATS_a, - FEAT_HIS_STATS_c, - FEAT_HIS_STATS_d, -@@ -139,6 +144,7 @@ - FEAT_HIS_STATS_q, - FEAT_HIS_STATS_R, - FEAT_HIS_STATS_r, -+ FEAT_HIS_STATS_S, - FEAT_HIS_STATS_s, - FEAT_HIS_STATS_t, - FEAT_HIS_STATS_T, -diff -r 1c62939e612b include/ircd_log.h ---- a/include/ircd_log.h Wed Feb 04 17:58:50 2009 +0100 -+++ b/include/ircd_log.h Wed Feb 04 18:04:57 2009 +0100 -@@ -55,6 +55,7 @@ - LS_OPERMODE, /**< Uses of OPMODE, CLEARMODE< etc. */ - LS_GLINE, /**< Adding, (de-)activating or removing GLINEs. */ - LS_JUPE, /**< Adding, (de-)activating or removing JUPEs. */ -+ LS_SPLIT, /**< Adding, (de-)activating or removing SPLITs. */ - LS_WHO, /**< Use of extended WHO privileges. */ - LS_NETWORK, /**< New server connections. */ - LS_OPERKILL, /**< Kills by IRC operators. */ -diff -r 1c62939e612b include/msg.h ---- a/include/msg.h Wed Feb 04 17:58:50 2009 +0100 -+++ b/include/msg.h Wed Feb 04 18:04:57 2009 +0100 -@@ -340,6 +340,10 @@ - #define TOK_JUPE "JU" - #define CMD_JUPE MSG_JUPE, TOK_JUPE - -+#define MSG_SPLIT "SPLIT" /* SPLIT */ -+#define TOK_SPLIT "SP" -+#define CMD_SPLIT MSG_SPLIT, TOK_SPLIT -+ - #define MSG_OPMODE "OPMODE" /* OPMO */ - #define TOK_OPMODE "OM" - #define CMD_OPMODE MSG_OPMODE, TOK_OPMODE -diff -r 1c62939e612b include/numeric.h ---- a/include/numeric.h Wed Feb 04 17:58:50 2009 +0100 -+++ b/include/numeric.h Wed Feb 04 18:04:57 2009 +0100 -@@ -118,6 +118,7 @@ - #define RPL_STATSALINE 226 /* Hybrid, Undernet */ - #define RPL_STATSWELCOME 227 /* QuakeNet extension */ - #define RPL_STATSQLINE 228 /* Undernet extension */ -+#define RPL_STATSSPLIT 229 /* QuakeNet extension */ - #define RPL_STATSHEADER 230 /* QuakeNet extension */ - - /* RPL_SERVICEINFO 231 unused */ -@@ -179,6 +180,8 @@ - #define RPL_STATSDLINE 275 /* Undernet extension */ - #define RPL_STATSRLINE 276 /* Undernet extension */ - -+#define RPL_SPLITLIST 278 /* QuakeNet extension */ -+#define RPL_ENDOFSPLITLIST 279 /* QuakeNet extension */ - #define RPL_GLIST 280 /* Undernet extension */ - #define RPL_ENDOFGLIST 281 /* Undernet extension */ - #define RPL_JUPELIST 282 /* Undernet extension - jupe -Kev */ -@@ -449,6 +452,7 @@ - - #define ERR_NOSUCHWELCOME 509 /* QuakeNet extension */ - -+#define ERR_NOSUCHSPLIT 510 /* QuakeNet extension */ - #define ERR_SILELISTFULL 511 /* Undernet extension */ - /* ERR_NOTIFYFULL 512 aircd */ - /* ERR_TOOMANYWATCH 512 Numeric List: Dalnet */ -diff -r 1c62939e612b include/split.h ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/include/split.h Wed Feb 04 18:04:57 2009 +0100 -@@ -0,0 +1,109 @@ -+#ifndef INCLUDED_split_h -+#define INCLUDED_split_h -+/* -+ * IRC - Internet Relay Chat, include/split.h -+ * Copyright (C) 1990 Jarkko Oikarinen and -+ * University of Oulu, Computing Center -+ * Copyright (C) 2000 Kevin L. Mitchell -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+/** @file -+ * @brief Interface and declarations for split server handling. -+ */ -+#ifndef INCLUDED_sys_types_h -+#include -+#define INCLUDED_sys_types_h -+#endif -+ -+ -+struct Client; -+struct StatDesc; -+ -+#define SPLIT_MAX_EXPIRE 2419200 /**< Maximum split expiration time (4 weeks). -+ * that an operator can use in /SPLIT -+ */ -+#define SPLIT_MAX_DRIFT 600 /**< Maximum drift in seconds allowed in lastmod -+ * timestamp -+ * when greater correct and throw warning -+ */ -+ -+/* Describes a SPLIT server entry. */ -+struct Split { -+ struct Split* sp_next; /**< Pointer to next Split. */ -+ struct Split** sp_prev_p; /**< Pointer to previous next pointer. */ -+ char* sp_server; /**< Name of server. */ -+ char* sp_reason; /**< Reason. */ -+ time_t sp_creation; /**< TODO: Creation time. What are we using this for then? */ -+ time_t sp_expire; /**< Expiration time. */ -+ time_t sp_lastmod; /**< Last modification time. */ -+ time_t sp_lifetime; /**< Life time. */ -+ unsigned int sp_flags; /**< Status flags. */ -+}; -+ -+/** Split state flags. */ -+#define SPLIT_ACTIVE 0x01 /**< Split is active. */ -+#define SPLIT_REMOVING 0x02 /**< Split is being force removed (instead of deactivated). */ -+#define SPLIT_BURST 0x04 /**< Split is for a server that is in progress of linking, -+ and will be destroyed at the end of burst */ -+ -+/* Actions to perform on a SPLIT. */ -+enum SplitAction { -+ SPLIT_ACTIVATE, /**< SPLIT should be activated. */ -+ SPLIT_DEACTIVATE, /**< SPLIT should be deactivated. */ -+ SPLIT_MODIFY, /**< SPLIT should be modified. */ -+ SPLIT_REMOVE /**< SPLIT should be removed. */ -+}; -+ -+/* Split update flags. */ -+#define SPLIT_EXPIRE 0x01 /**< Expiration time update. */ -+#define SPLIT_LIFETIME 0x02 /**< Record lifetime update. */ -+#define SPLIT_REASON 0x04 /**< Reason update. */ -+ -+/* mask for Split update flags. */ -+#define SPLIT_UPDATE (SPLIT_EXPIRE | SPLIT_LIFETIME | SPLIT_REASON) -+ -+/* test whether a split entry is active. */ -+#define SplitIsActive(s) ((s)->sp_flags & SPLIT_ACTIVE) -+/* test whether a split entry is marked for forced removal. */ -+#define SplitIsRemoving(s) ((s)->sp_flags & SPLIT_REMOVING) -+/* test whether a split entry is part of a netmerge. */ -+#define SplitIsBurst(s) ((s)->sp_flags & SPLIT_BURST) -+ -+extern int split_add(struct Client *cptr, struct Client *sptr, -+ char *server, const char *reason, -+ time_t creation, time_t expire, time_t lastmod, time_t lifetime, -+ unsigned int flags); -+extern int split_modify(struct Client *cptr, struct Client *sptr, -+ struct Split *split, enum SplitAction action, const char *reason, -+ time_t creation, time_t expire, time_t lastmod, time_t lifetime, -+ unsigned int flags); -+extern int split_remove(struct Client *cptr, struct Client *sptr, -+ struct Split *split, const char *reason); -+ -+extern struct Split* split_find(char *server); -+extern void split_free(struct Split *split); -+extern int split_expire(struct Split* split); -+extern void split_burst(struct Client *cptr); -+extern int split_resend(struct Client *cptr, struct Split *split); -+extern int split_list(struct Client *sptr, char *server); -+extern void split_newserver(struct Client *acptr); -+extern int split_netmerge(struct Client *sptr); -+extern int split_netbreak(struct Client *victim, const char *reason); -+extern void split_conf(); -+extern void split_stats(struct Client *sptr, const struct StatDesc *sd, char *param); -+extern int split_memory_count(size_t *sp_size); -+ -+#endif /* INCLUDED_split_h */ -diff -r 1c62939e612b ircd/Makefile.in ---- a/ircd/Makefile.in Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/Makefile.in Wed Feb 04 18:04:57 2009 +0100 -@@ -173,6 +173,7 @@ - m_sethost.c \ - m_settime.c \ - m_silence.c \ -+ m_split.c \ - m_squit.c \ - m_staff.c \ - m_stats.c \ -@@ -214,6 +215,7 @@ - s_stats.c \ - s_user.c \ - send.c \ -+ split.c \ - uping.c \ - userload.c \ - welcome.c \ -@@ -1055,6 +1057,15 @@ - ../include/ircd_chattr.h ../include/list.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ - ../include/send.h ../include/struct.h -+m_split.o: m_split.c ../config.h ../include/client.h ../include/ircd_defs.h \ -+ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ -+ ../config.h ../include/ircd_handler.h ../include/res.h \ -+ ../include/capab.h ../include/split.h ../include/hash.h \ -+ ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ -+ ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ -+ ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ -+ ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ -+ ../include/client.h ../include/s_misc.h ../include/send.h - m_squit.o: m_squit.c ../config.h ../include/client.h \ - ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_events.h ../config.h ../include/ircd_handler.h \ -@@ -1344,6 +1355,7 @@ - ../include/msgq.h ../include/numeric.h ../include/numnicks.h \ - ../include/res.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/s_user.h ../include/s_stats.h ../include/send.h \ -+ ../include/split.h \ - ../include/struct.h ../include/sys.h ../include/whowas.h - s_err.o: s_err.c ../config.h ../include/numeric.h ../include/ircd_log.h \ - ../include/s_debug.h ../config.h ../include/ircd_defs.h -@@ -1429,6 +1441,16 @@ - ../include/msg.h ../include/numnicks.h ../include/parse.h \ - ../include/s_bsd.h ../include/s_debug.h ../include/s_misc.h \ - ../include/s_user.h ../include/struct.h ../include/sys.h -+split.o: split.c ../config.h ../include/split.h ../include/client.h \ -+ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ -+ ../include/ircd_events.h ../config.h ../include/ircd_handler.h \ -+ ../include/res.h ../include/capab.h ../include/hash.h ../include/ircd.h \ -+ ../include/struct.h ../include/ircd_alloc.h ../include/ircd_features.h \ -+ ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ -+ ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ -+ ../include/numeric.h ../include/numnicks.h ../include/s_bsd.h \ -+ ../include/s_misc.h ../include/send.h ../include/struct.h \ -+ ../include/sys.h - uping.o: uping.c ../config.h ../include/uping.h ../include/ircd_defs.h \ - ../include/ircd_events.h ../config.h ../include/res.h \ - ../include/client.h ../include/dbuf.h ../include/msgq.h \ -diff -r 1c62939e612b ircd/client.c ---- a/ircd/client.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/client.c Wed Feb 04 18:04:57 2009 +0100 -@@ -185,6 +185,7 @@ - FlagSet(&privs_local, PRIV_DISPLAY); - FlagSet(&privs_local, PRIV_FORCE_LOCAL_OPMODE); - FlagSet(&privs_local, PRIV_LOCAL_WELCOME); -+ FlagSet(&privs_local, PRIV_SPLIT); - FlagClr(&privs_local, PRIV_STAFF); - FlagClr(&privs_local, PRIV_CLAIM_NICK); - FlagClr(&privs_local, PRIV_GLINE_LOOKUP); -@@ -292,6 +293,7 @@ - P(STAFF), P(CLAIM_NICK), P(GLINE_LOOKUP), P(HIDE_CHANS), - P(CHECK_CHANNEL), - P(WELCOME), P(LOCAL_WELCOME), -+ P(SPLIT), - #undef P - { 0, 0 } - }; -diff -r 1c62939e612b ircd/ircd.c ---- a/ircd/ircd.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/ircd.c Wed Feb 04 18:04:57 2009 +0100 -@@ -55,6 +55,7 @@ - #include "s_misc.h" - #include "s_stats.h" - #include "send.h" -+#include "split.h" - #include "sys.h" - #include "uping.h" - #include "userload.h" -@@ -763,6 +764,9 @@ - Debug((DEBUG_NOTICE, "Server ready...")); - log_write(LS_SYSTEM, L_NOTICE, 0, "Server Ready"); - -+ /* create SPLITs */ -+ split_conf(); -+ - event_loop(); - - return 0; -diff -r 1c62939e612b ircd/ircd_features.c ---- a/ircd/ircd_features.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/ircd_features.c Wed Feb 04 18:04:57 2009 +0100 -@@ -366,6 +366,10 @@ - F_B(SETHOST_USER, 0, 0, 0), - F_B(SETHOST_AUTO, 0, 0, 0), - -+ /* SPLIT */ -+ F_B(SPLIT, 0, 1, 0), -+ F_I(SPLIT_AUTO_EXPIRE, 0, 604800, 0), -+ - /* HEAD_IN_SAND Features */ - F_B(HIS_SNOTICES, 0, 1, 0), - F_B(HIS_SNOTICES_OPER_ONLY, 0, 1, 0), -@@ -374,6 +378,7 @@ - F_B(HIS_MAP, 0, 1, 0), - F_B(HIS_LINKS, 0, 1, 0), - F_B(HIS_TRACE, 0, 1, 0), -+ F_B(HIS_SPLIT, 0, 1, 0), - F_B(HIS_STATS_a, 0, 1, 0), - F_B(HIS_STATS_c, 0, 1, 0), - F_B(HIS_STATS_d, 0, 1, 0), -@@ -393,6 +398,7 @@ - F_B(HIS_STATS_q, 0, 1, 0), - F_B(HIS_STATS_R, 0, 1, 0), - F_B(HIS_STATS_r, 0, 1, 0), -+ F_B(HIS_STATS_S, 0, 1, 0), - F_B(HIS_STATS_s, 0, 1, 0), - F_B(HIS_STATS_t, 0, 1, 0), - F_B(HIS_STATS_T, 0, 1, 0), -diff -r 1c62939e612b ircd/ircd_lexer.l ---- a/ircd/ircd_lexer.l Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/ircd_lexer.l Wed Feb 04 18:04:57 2009 +0100 -@@ -175,6 +175,7 @@ - { "check_channel", TPRIV_CHECK_CHANNEL }, - { "local_welcome", TPRIV_LOCAL_WELCOME }, - { "welcome", TPRIV_WELCOME }, -+ { "split", TPRIV_SPLIT }, - { NULL, 0 } - }; - static int ntokens; -diff -r 1c62939e612b ircd/ircd_log.c ---- a/ircd/ircd_log.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/ircd_log.c Wed Feb 04 18:04:57 2009 +0100 -@@ -154,6 +154,7 @@ - S(OPERMODE, -1, SNO_HACK4), - S(GLINE, -1, SNO_GLINE), - S(JUPE, -1, SNO_NETWORK), -+ S(SPLIT, -1, SNO_NETWORK), - S(WHO, -1, 0), - S(NETWORK, -1, SNO_NETWORK), - S(OPERKILL, -1, 0), -diff -r 1c62939e612b ircd/ircd_parser.y ---- a/ircd/ircd_parser.y Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/ircd_parser.y Wed Feb 04 18:04:57 2009 +0100 -@@ -193,6 +193,7 @@ - %token TPRIV_STAFF TPRIV_CLAIM_NICK TPRIV_GLINE_LOOKUP TPRIV_HIDE_CHANS - %token TPRIV_CHECK_CHANNEL - %token TPRIV_LOCAL_WELCOME TPRIV_WELCOME -+%token TPRIV_SPLIT - /* and some types... */ - %type sizespec - %type timespec timefactor factoredtimes factoredtime -@@ -716,6 +717,7 @@ - TPRIV_HIDE_CHANS { $$ = PRIV_HIDE_CHANS; } | - TPRIV_LOCAL_WELCOME { $$ = PRIV_LOCAL_WELCOME; } | - TPRIV_WELCOME { $$ = PRIV_WELCOME; } | -+ TPRIV_SPLIT { $$ = PRIV_SPLIT; } | - TPRIV_PARANOID { $$ = PRIV_PARANOID; } ; - yesorno: YES { $$ = 1; } | NO { $$ = 0; }; - -diff -r 1c62939e612b ircd/m_endburst.c ---- a/ircd/m_endburst.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/m_endburst.c Wed Feb 04 18:04:57 2009 +0100 -@@ -85,6 +85,7 @@ - #include "client.h" - #include "hash.h" - #include "ircd.h" -+#include "ircd_features.h" - #include "ircd_log.h" - #include "ircd_reply.h" - #include "ircd_string.h" -@@ -92,6 +93,7 @@ - #include "numeric.h" - #include "numnicks.h" - #include "send.h" -+#include "split.h" - - /* #include -- Now using assert in ircd_log.h */ - -@@ -125,6 +127,7 @@ - int ms_end_of_burst(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) - { - struct Channel *chan, *next_chan; -+ int split; - - assert(0 != cptr); - assert(0 != sptr); -@@ -135,6 +138,10 @@ - dump_map(sptr, "*", 0, report_new_links, 0); - sendto_opmask_butone(0, SNO_NETWORK, "Completed net.burst from %C.", - sptr); -+ /* cleanup SPLITs, but only bother ops when FEAT_SPLIT is enabled. */ -+ split = split_netmerge(sptr); -+ if (feature_bool(FEAT_SPLIT)) -+ sendto_opmask_butone(0, SNO_NETWORK, "Removed %d SPLIT entries.", split); - if (MyConnect(sptr)) - sendcmdto_one(&me, CMD_END_OF_BURST_ACK, sptr, ""); - -diff -r 1c62939e612b ircd/m_reburst.c ---- a/ircd/m_reburst.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/m_reburst.c Wed Feb 04 18:04:57 2009 +0100 -@@ -102,6 +102,7 @@ - #include "ircd_snprintf.h" - #include "gline.h" - #include "jupe.h" -+#include "split.h" - - /* #include -- Now using assert in ircd_log.h */ - #include -@@ -130,6 +131,10 @@ - case 'J': - jupe_burst(sptr); - break; -+ case 's': -+ case 'S': -+ split_burst(sptr); -+ break; - default: - break; - } -diff -r 1c62939e612b ircd/m_server.c ---- a/ircd/m_server.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/m_server.c Wed Feb 04 18:04:57 2009 +0100 -@@ -47,6 +47,7 @@ - #include "s_misc.h" - #include "s_serv.h" - #include "send.h" -+#include "split.h" - #include "userload.h" - - /* #include -- Now using assert in ircd_log.h */ -@@ -764,6 +765,9 @@ - sendto_opmask_butone(0, SNO_NETWORK, "Net junction: %s %s", - cli_name(sptr), cli_name(acptr)); - } -+ /* new server - mark SPLIT for this server */ -+ split_newserver(acptr); -+ - /* - * Old sendto_serv_but_one() call removed because we now need to send - * different names to different servers (domain name matching). -diff -r 1c62939e612b ircd/m_split.c ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/ircd/m_split.c Wed Feb 04 18:04:57 2009 +0100 -@@ -0,0 +1,400 @@ -+/* -+ * IRC - Internet Relay Chat, ircd/m_split.c -+ * Copyright (C) 1990 Jarkko Oikarinen and -+ * University of Oulu, Computing Center -+ * Copyright (C) 2000 Kevin L. Mitchell -+ * -+ * See file AUTHORS in IRC package for additional names of -+ * the programmers. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 1, or (at your option) -+ * any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ */ -+ -+/* -+ * m_functions execute protocol messages on this server: -+ * -+ * cptr is always NON-NULL, pointing to a *LOCAL* client -+ * structure (with an open socket connected!). This -+ * identifies the physical socket where the message -+ * originated (or which caused the m_function to be -+ * executed--some m_functions may call others...). -+ * -+ * sptr is the source of the message, defined by the -+ * prefix part of the message if present. If not -+ * or prefix not found, then sptr==cptr. -+ * -+ * (!IsServer(cptr)) => (cptr == sptr), because -+ * prefixes are taken *only* from servers... -+ * -+ * (IsServer(cptr)) -+ * (sptr == cptr) => the message didn't -+ * have the prefix. -+ * -+ * (sptr != cptr && IsServer(sptr) means -+ * the prefix specified servername. (?) -+ * -+ * (sptr != cptr && !IsServer(sptr) means -+ * that message originated from a remote -+ * user (not local). -+ * -+ * combining -+ * -+ * (!IsServer(sptr)) means that, sptr can safely -+ * taken as defining the target structure of the -+ * message in this server. -+ * -+ * *Always* true (if 'parse' and others are working correct): -+ * -+ * 1) sptr->from == cptr (note: cptr->from == cptr) -+ * -+ * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr -+ * *cannot* be a local connection, unless it's -+ * actually cptr!). [MyConnect(x) should probably -+ * be defined as (x == x->from) --msa ] -+ * -+ * parc number of variable parameter strings (if zero, -+ * parv is allowed to be NULL) -+ * -+ * parv a NULL terminated list of parameter pointers, -+ * -+ * parv[0], sender (prefix string), if not present -+ * this points to an empty string. -+ * parv[1]...parv[parc-1] -+ * pointers to additional parameters -+ * parv[parc] == NULL, *always* -+ * -+ * note: it is guaranteed that parv[0]..parv[parc-1] are all -+ * non-NULL pointers. -+ */ -+#include "config.h" -+ -+#include "client.h" -+#include "split.h" -+#include "hash.h" -+#include "ircd.h" -+#include "ircd_features.h" -+#include "ircd_log.h" -+#include "ircd_reply.h" -+#include "ircd_string.h" -+#include "match.h" -+#include "msg.h" -+#include "numeric.h" -+#include "numnicks.h" -+#include "s_conf.h" -+#include "s_debug.h" -+#include "s_misc.h" -+#include "send.h" -+ -+/* #include -- Now using assert in ircd_log.h */ -+#include -+#include -+ -+/* -+ * ms_split - server message handler -+ * -+ * parv[0] = Send prefix -+ * parv[1] = (+|-) -+ * parv[2] = Creation time -+ * parv[3] = Expiration time -+ * parv[4] = Last modification time -+ * parv[5] = Life time -+ * parv[6] = Comment -+ * -+ */ -+int ms_split(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) -+{ -+ struct Split *asplit = 0; -+ unsigned int flags = 0; -+ enum SplitAction action = SPLIT_MODIFY; -+ time_t creation = 0, expire = 0, lastmod = 0, lifetime = 0; -+ char *server; -+ const char *reason = "No reason"; -+ -+ /* reason is optional - for lazy services, we always send it */ -+ if (parc < 5) { -+ protocol_violation(sptr, "Too few parameters for SPLIT (got %d - need at least 5)", parc); -+ return need_more_params(sptr, "SPLIT"); -+ } -+ -+ /* server param */ -+ server = parv[1]; -+ -+ /* check for ! prefix - force removing */ -+ if (*server == '!') { -+ server++; -+ action = SPLIT_REMOVE; -+ } -+ -+ /* check for + and - prefix */ -+ switch (*server) { -+ case '+': -+ if (action != SPLIT_REMOVE) -+ action = SPLIT_ACTIVATE; -+ server++; -+ break; -+ -+ case '-': -+ if (action != SPLIT_REMOVE) -+ action = SPLIT_DEACTIVATE; -+ server++; -+ break; -+ } -+ -+ /* Next, try to find the split entry... */ -+ asplit = split_find(server); -+ -+ /* We now have all the pieces to tell us what we've got; let's put -+ * it all together and convert the rest of the arguments. -+ */ -+ -+ /* cannot modify a split entry that does not exist - remap to activate */ -+ if (!asplit && action == SPLIT_MODIFY) -+ action = SPLIT_ACTIVATE; -+ -+ /* set all flags for modification */ -+ if (asplit && action != SPLIT_REMOVE) -+ flags = SPLIT_UPDATE; -+ -+ /* set the things we need */ -+ creation = atoi(parv[2]); -+ expire = atoi(parv[3]); -+ lastmod = atoi(parv[4]); -+ lifetime = atoi(parv[5]); -+ -+ /* got a reason too */ -+ if (parc > 5) -+ reason = parv[parc - 1]; -+ else -+ flags &= ~SPLIT_REASON; -+ -+ /* debug */ -+ Debug((DEBUG_DEBUG, "I have a SPLIT I am acting upon now; " -+ "server %s, action %s, creation %Tu, expire %Tu, " -+ "lastmod %Tu, lifetime %Tu, reason: %s; split %s!", server, -+ action == SPLIT_REMOVE ? "!-" : -+ (action == SPLIT_ACTIVATE ? "+" : -+ (action == SPLIT_DEACTIVATE ? "-" : "(MODIFY)")), -+ creation, expire, lastmod, lifetime, reason, -+ asplit ? "EXISTS" : "does not exist")); -+ -+ /* modify or remove an existing SPLIT */ -+ if (asplit) { -+ if (action == SPLIT_REMOVE) -+ return split_remove(cptr, sptr, asplit, reason); -+ return split_modify(cptr, sptr, asplit, action, reason, creation, expire, -+ lastmod, lifetime, flags); -+ } -+ -+ /* desynch or cross - we do not have it so we cannot remove it */ -+ /* TODO: manually propagate the message ? -+ * -+ * but if we do not have it, can our downlinks have it? -+ * they could if my oper force removed it earlier, and then my downlinks linked -+ * no, then they would have bursted it again to us.. argh -+ */ -+ if (!asplit && action == SPLIT_REMOVE) -+ return 0; -+ -+ /* this should not happen */ -+ assert(action != SPLIT_MODIFY); -+ assert(action != SPLIT_REMOVE); -+ -+ /* create a new SPLIT */ -+ return split_add(cptr, sptr, server, reason, creation, expire, lastmod, lifetime, -+ action == SPLIT_ACTIVATE ? SPLIT_ACTIVE : 0); -+} -+ -+ -+/* -+ * mo_split - oper message handler -+ * -+ * Local listing: 1 or 2 params -+ * parv[0] = Send prefix -+ * parv[1] = [Server or mask to match] -+ * -+ * Add or modify entry: 2, 3 or 4 params -+ * parv[0] = Send prefix -+ * parv[1] = [+|-] -+ * parv[2] = [Expiration offset] (required for new) -+ * parv[3] = [Comment] (required for new) -+ * -+ */ -+int mo_split(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) -+{ -+ struct Split *asplit = 0; -+ unsigned int flags = 0; -+ enum SplitAction action = SPLIT_MODIFY; -+ time_t expire = 0, lastmod = TStime(), creation = TStime(); -+ char *server, *end; -+ const char *reason = NULL; -+ -+ /* TODO: check PRIV_SPLIT here? */ -+ /* check HIS and privs */ -+ if (feature_bool(FEAT_HIS_SPLIT) && !HasPriv(sptr, PRIV_ROUTEINFO)) -+ return send_reply(sptr, ERR_NOPRIVILEGES); -+ -+ /* listing */ -+ if (parc < 2) -+ return split_list(sptr, 0); -+ -+ /* set server */ -+ server = parv[1]; -+ -+ /* ! prefix - force removal */ -+ if (*server == '!') { -+ server++; -+ action = SPLIT_REMOVE; -+ } -+ -+ /* handle + and - */ -+ switch (*server) { -+ case '+': -+ if (action != SPLIT_REMOVE) -+ action = SPLIT_ACTIVATE; -+ server++; -+ break; -+ -+ case '-': -+ if (action != SPLIT_REMOVE) -+ action = SPLIT_DEACTIVATE; -+ server++; -+ break; -+ } -+ -+ /* user wants listing */ -+ if (action == SPLIT_MODIFY && parc == 2) -+ return split_list(sptr, server); -+ -+ /* TODO: but allow force removal when disabled? */ -+ /* check feature and privs */ -+ if (!feature_bool(FEAT_SPLIT)) -+ return send_reply(sptr, ERR_DISABLED, "SPLIT"); -+ else if (!HasPriv(sptr, PRIV_SPLIT)) -+ return send_reply(sptr, ERR_NOPRIVILEGES); -+ -+ /* if we have an expire, this must be it */ -+ if (parc > 2) -+ expire = strtol(parv[2], &end, 10); -+ -+ /* got reason and expire */ -+ if (parc > 3) { -+ flags |= SPLIT_EXPIRE; -+ flags |= SPLIT_REASON; -+ } -+ /* got reason or expire */ -+ else if (parc > 2) { -+ if (*end != '\0') -+ flags |= SPLIT_REASON; -+ else -+ flags |= SPLIT_EXPIRE; -+ } -+ -+ /* set reason */ -+ if (flags & SPLIT_REASON) { -+ reason = parv[parc - 1]; -+ /* ignore empty reason */ -+ if (EmptyString(reason)) -+ flags &= ~SPLIT_REASON; -+ } -+ -+ /* bad expire */ -+ if (flags & SPLIT_EXPIRE && *end != '\0') -+ return send_reply(sptr, SND_EXPLICIT | ERR_BADEXPIRE, "%s :Bad expire time", parv[2]); -+ -+ /* require a reason for forced removal */ -+ if (!(flags & SPLIT_REASON) && action == SPLIT_REMOVE) -+ return need_more_params(sptr, "SPLIT"); -+ -+ /* we got expire */ -+ if (flags & SPLIT_EXPIRE) { -+ if (expire == 0) /* dummy value 0 given, no change to expire */ -+ flags &= ~SPLIT_EXPIRE; -+ else /* turn expire into timestamp */ -+ expire += TStime(); -+ } -+ -+ /* we have all we need - find the split */ -+ asplit = split_find(server); -+ -+ /* SPLIT not found and thus we cannot: -+ * remove SPLIT we do not have -+ * add new SPLIT without expire and reason -+ */ -+ if (!asplit && -+ ((action == SPLIT_REMOVE) || -+ (action == SPLIT_ACTIVATE && !reason) || -+ (action == SPLIT_DEACTIVATE && !reason) || -+ (action == SPLIT_MODIFY && !reason))) -+ return send_reply(sptr, ERR_NOSUCHSPLIT, server); -+ -+ /* cannot modify a split entry that does not exist - remap to activate */ -+ if (!asplit && action == SPLIT_MODIFY) -+ action = SPLIT_ACTIVATE; -+ -+ /* debug */ -+ Debug((DEBUG_DEBUG, "I have a SPLIT I am acting upon now; " -+ "server %s, action %s, expire %Tu, " -+ "reason: %s; split %s! (fields present: %s %s)", server, -+ action == SPLIT_REMOVE ? "!-" : -+ (action == SPLIT_ACTIVATE ? "+" : -+ (action == SPLIT_DEACTIVATE ? "-" : "(MODIFY)")), -+ expire, reason, asplit ? "EXISTS" : "does not exist", -+ flags & SPLIT_EXPIRE ? "expire" : "", -+ flags & SPLIT_REASON ? "reason" : "")); -+ -+ /* modify or remove an existing SPLIT */ -+ if (asplit) { -+ if (action == SPLIT_REMOVE) -+ return split_remove(cptr, sptr, asplit, reason); -+ return split_modify(cptr, sptr, asplit, action, reason, -+ asplit->sp_creation, expire, lastmod, asplit->sp_lifetime, flags); -+ } -+ -+ /* this should not happen */ -+ assert(action != SPLIT_MODIFY); -+ assert(action != SPLIT_REMOVE); -+ -+ /* create a new SPLIT */ -+ return split_add(cptr, sptr, server, reason, -+ creation, expire, lastmod, expire, -+ (action == SPLIT_ACTIVATE) ? SPLIT_ACTIVE : 0); -+} -+ -+ -+/* -+ * m_split - user message handler -+ * -+ * parv[0] = Send prefix -+ * parv[1] = [] -+ * -+ */ -+int m_split(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) -+{ -+ -+ /* ordinary users are not allowed to see it when HIS_SPLIT is true -+ * and are not allowed to to give more than two parameters -+ * to make changes -+ */ -+ if (feature_bool(FEAT_HIS_SPLIT) || parc > 2) -+ return send_reply(sptr, ERR_NOPRIVILEGES); -+ -+ /* listing all */ -+ if (parc < 2) -+ return split_list(sptr, 0); -+ -+ /* looking for a match */ -+ return split_list(sptr, parv[1]); -+} -diff -r 1c62939e612b ircd/parse.c ---- a/ircd/parse.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/parse.c Wed Feb 04 18:04:57 2009 +0100 -@@ -513,6 +513,13 @@ - { m_unregistered, m_not_oper, ms_jupe, mo_jupe, m_ignore, mh_jupe } - }, - { -+ MSG_SPLIT, -+ TOK_SPLIT, -+ 0, MAXPARA, MFLG_SLOW, 0, NULL, -+ /* UNREG, CLIENT, SERVER, OPER, SERVICE, HELP */ -+ { m_unregistered, m_split, ms_split, mo_split, m_ignore, mh_nohelp } -+ }, -+ { - MSG_OPMODE, - TOK_OPMODE, - 0, MAXPARA, MFLG_SLOW, 0, NULL, -diff -r 1c62939e612b ircd/s_conf.c ---- a/ircd/s_conf.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/s_conf.c Wed Feb 04 18:04:57 2009 +0100 -@@ -53,6 +53,7 @@ - #include "s_debug.h" - #include "s_misc.h" - #include "send.h" -+#include "split.h" - #include "struct.h" - #include "sys.h" - -@@ -1005,6 +1006,7 @@ - } - - attach_conf_uworld(&me); -+ split_conf(); - - return ret; - } -diff -r 1c62939e612b ircd/s_debug.c ---- a/ircd/s_debug.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/s_debug.c Wed Feb 04 18:04:57 2009 +0100 -@@ -48,6 +48,7 @@ - #include "s_user.h" - #include "s_stats.h" - #include "send.h" -+#include "split.h" - #include "struct.h" - #include "sys.h" - #include "whowas.h" -@@ -231,7 +232,8 @@ - aw = 0, /* aways set */ - wwa = 0, /* whowas aways */ - gl = 0, /* glines */ -- ju = 0; /* jupes */ -+ ju = 0, /* jupes */ -+ sp = 0; /* splits */ - - size_t chm = 0, /* memory used by channels */ - chbm = 0, /* memory used by channel bans */ -@@ -244,6 +246,7 @@ - wwm = 0, /* whowas array memory used */ - glm = 0, /* memory used by glines */ - jum = 0, /* memory used by jupes */ -+ spm = 0, /* memory used by splits */ - com = 0, /* memory used by conf lines */ - dbufs_allocated = 0, /* memory used by dbufs */ - dbufs_used = 0, /* memory used by dbufs */ -@@ -348,8 +351,9 @@ - - gl = gline_memory_count(&glm); - ju = jupe_memory_count(&jum); -+ sp = split_memory_count(&spm); - send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, -- ":Glines %d(%zu) Jupes %d(%zu)", gl, glm, ju, jum); -+ ":Glines %d(%zu) Jupes %d(%zu) Splits %d(%zu)", gl, glm, ju, jum, sp, spm); - - send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, - ":Hash: client %d(%zu), chan is the same", HASHSIZE, -diff -r 1c62939e612b ircd/s_err.c ---- a/ircd/s_err.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/s_err.c Wed Feb 04 18:04:57 2009 +0100 -@@ -490,7 +490,7 @@ - /* 228 */ - { RPL_STATSQLINE, "Q %s :%s", "228" }, - /* 229 */ -- { 0 }, -+ { RPL_STATSSPLIT, "S %s %d %d %d %d %c :%s", "229" }, - /* 230 */ - { RPL_STATSHEADER, 0, "230" }, - /* 231 */ -@@ -588,9 +588,9 @@ - /* 277 */ - { 0 }, - /* 278 */ -- { 0 }, -+ { RPL_SPLITLIST, "%s %Tu %Tu %Tu %Tu %c :%s", "278" }, - /* 279 */ -- { 0 }, -+ { RPL_ENDOFSPLITLIST, ":End of Split List", "279" }, - /* 280 */ - { RPL_GLIST, "%s%s%s%s%s %Tu %Tu %Tu %s %s%s%c :%s", "280" }, - /* 281 */ -@@ -1052,7 +1052,7 @@ - /* 509 */ - { ERR_NOSUCHWELCOME, "%s :No such welcome", "509" }, - /* 510 */ -- { 0 }, -+ { ERR_NOSUCHSPLIT, "%s :No such split", "510" }, - /* 511 */ - { ERR_SILELISTFULL, "%s :Your silence list is full", "511" }, - /* 512 */ -diff -r 1c62939e612b ircd/s_misc.c ---- a/ircd/s_misc.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/s_misc.c Wed Feb 04 18:04:57 2009 +0100 -@@ -53,6 +53,7 @@ - #include "s_stats.h" - #include "s_user.h" - #include "send.h" -+#include "split.h" - #include "struct.h" - #include "sys.h" - #include "uping.h" -@@ -391,6 +392,7 @@ - time_t on_for; - - char comment1[HOSTLEN + HOSTLEN + 2]; -+ char splitreason[BUFSIZE]; - assert(killer); - if (MyConnect(victim)) - { -@@ -497,6 +499,15 @@ - sendto_opmask_butone(0, SNO_NETWORK, "Net break: %C %C (%s)", - cli_serv(victim)->up, victim, comment); - dump_map(victim, "*", 0, report_lost_links, 0); -+ if (feature_bool(FEAT_SPLIT)) { -+ /* TODO: remote & local SQUIT ? servername oper is on? */ -+ ircd_snprintf(0, splitreason, sizeof(splitreason), -+ "Net break: %C %C (%s%s%s%s)", cli_serv(victim)->up, victim, -+ IsUser(killer) ? "SQUIT by " : "", IsUser(killer) ? cli_name(killer) : "", -+ IsUser(killer) ? ": " : "", comment); -+ sendto_opmask_butone(0, SNO_NETWORK, "Created %d SPLIT entries.", -+ split_netbreak(victim, splitreason)); -+ } - } - - /* -diff -r 1c62939e612b ircd/s_serv.c ---- a/ircd/s_serv.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/s_serv.c Wed Feb 04 18:04:57 2009 +0100 -@@ -54,6 +54,7 @@ - #include "s_misc.h" - #include "s_user.h" - #include "send.h" -+#include "split.h" - #include "struct.h" - #include "sys.h" - #include "userload.h" -@@ -197,6 +198,7 @@ - */ - gline_burst(cptr); - jupe_burst(cptr); -+ split_burst(cptr); - welcome_burst(cptr); - - /* -diff -r 1c62939e612b ircd/s_stats.c ---- a/ircd/s_stats.c Wed Feb 04 17:58:50 2009 +0100 -+++ b/ircd/s_stats.c Wed Feb 04 18:04:57 2009 +0100 -@@ -52,6 +52,7 @@ - #include "s_stats.h" - #include "s_user.h" - #include "send.h" -+#include "split.h" - #include "struct.h" - #include "userload.h" - #include "welcome.h" -@@ -669,7 +670,10 @@ - send_usage, 0, - "System resource usage (Debug only)." }, - #endif -- { 's', "spoofhosts", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_s, -+ { 'S', "splits", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM | STAT_FLAG_CASESENS), FEAT_HIS_STATS_S, -+ split_stats, 0, -+ "Server SPLITs information."}, -+ { 's', "spoofhosts", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM | STAT_FLAG_CASESENS), FEAT_HIS_STATS_s, - stats_sline, 0, - "Spoofed hosts information." }, - { 'T', "motds", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_T, -diff -r 1c62939e612b ircd/split.c ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/ircd/split.c Wed Feb 04 18:04:57 2009 +0100 -@@ -0,0 +1,873 @@ -+/* -+ * IRC - Internet Relay Chat, ircd/split.c -+ * Copyright (C) 1990 Jarkko Oikarinen and -+ * University of Oulu, Finland -+ * Copyright (C) 2000 Kevin L. Mitchell -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 1, or (at your option) -+ * any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+/** @file -+ * @brief Implementation of split server handling functions. -+ */ -+#include "config.h" -+ -+#include "split.h" -+#include "client.h" -+#include "hash.h" -+#include "ircd.h" -+#include "ircd_alloc.h" -+#include "ircd_features.h" -+#include "ircd_log.h" -+#include "ircd_reply.h" -+#include "ircd_snprintf.h" -+#include "ircd_string.h" -+#include "list.h" -+#include "match.h" -+#include "msg.h" -+#include "numeric.h" -+#include "numnicks.h" -+#include "s_conf.h" -+#include "s_bsd.h" -+#include "s_debug.h" -+#include "s_misc.h" -+#include "send.h" -+#include "struct.h" -+#include "sys.h" /* FALSE bleah */ -+ -+/* #include -- Now using assert in ircd_log.h */ -+#include -+ -+/** List of split entries. */ -+static struct Split *GlobalSplitList = 0; -+ -+/** Allocate a new Split entry with the given parameters. -+ * @param[in] server Server name for split entry. -+ * @param[in] reason Reason for the split entry. -+ * @param[in] creation Creation time for split entry. -+ * @param[in] expire Expiration time for split entry. -+ * @param[in] lastmod Last modification time for split entry. -+ * @param[in] lifetime Life time for split entry. -+ * @param[in] flags Flags to set for the split entry. -+ */ -+static struct Split * -+split_make(char *server, const char *reason, -+ time_t creation, time_t expire, time_t lastmod, time_t lifetime, -+ unsigned int flags) -+{ -+ struct Split *asplit; -+ char sp_server[HOSTLEN+1]; -+ char sp_reason[TOPICLEN+1]; -+ -+ /* alloc memory */ -+ asplit = (struct Split*) MyMalloc(sizeof(struct Split)); -+ -+ /* we should have it now */ -+ assert(0 != asplit); -+ -+ memset(asplit, 0, sizeof(*asplit)); -+ ircd_strncpy(sp_server, server, HOSTLEN); -+ DupString(asplit->sp_server, sp_server); -+ /* TODO: prefix the reason here with the opername/ID? */ -+ ircd_strncpy(sp_reason, reason, TOPICLEN); -+ DupString(asplit->sp_reason, sp_reason); -+ asplit->sp_creation = creation; -+ asplit->sp_expire = expire; -+ asplit->sp_lastmod = lastmod; -+ asplit->sp_lifetime = lifetime; -+ /* set split flags - only save SPLIT_ACTIVE */ -+ asplit->sp_flags = flags & SPLIT_ACTIVE; -+ -+ /* link it into the list */ -+ asplit->sp_next = GlobalSplitList; -+ asplit->sp_prev_p = &GlobalSplitList; -+ if (GlobalSplitList) -+ GlobalSplitList->sp_prev_p = &asplit->sp_next; -+ GlobalSplitList = asplit; -+ -+ return asplit; -+} -+ -+ -+/** Forward a split entry to another server. -+ * @param[in] cptr Local client that sent us the split entry. -+ * @param[in] sptr Originator of the split entry. -+ * @param[in] split Split entry to forward. -+ * @param[in] reason Reason to send upstream (used by split_remove) -+ */ -+static void -+split_propagate(struct Client *cptr, struct Client *sptr, -+ struct Split *split, const char *reason) -+{ -+ sendcmdto_serv_butone(sptr, CMD_SPLIT, cptr, "%s%c%s %Tu %Tu %Tu %Tu :%s", -+ SplitIsRemoving(split) ? "!" : "", -+ SplitIsActive(split) && !SplitIsRemoving(split) ? '+' : '-', /* always !- not !+ */ -+ split->sp_server, split->sp_creation, split->sp_expire, -+ split->sp_lastmod, split->sp_lifetime, -+ EmptyString(reason) ? split->sp_reason : reason); -+} -+ -+ -+/** Add a new server split entry. -+ * @param[in] cptr Local client that sent us the split entry. -+ * @param[in] sptr Originator of the split entry. -+ * @param[in] server Server name to split entry. -+ * @param[in] reason Reason for the split entry. -+ * @param[in] expire Expiration timestamp. -+ * @param[in] lastmod Last modification timestamp. -+ * @param[in] flags Flags to set on the split entry. -+ * @return Zero -+ */ -+int -+split_add(struct Client *cptr, struct Client *sptr, char *server, const char *reason, -+ time_t creation, time_t expire, time_t lastmod, time_t lifetime, -+ unsigned int flags) -+{ -+ -+ struct Split *split; -+ char noreason[BUFSIZE]; -+ static time_t rate; -+ -+ assert(NULL != cptr); -+ assert(NULL != sptr); -+ assert(NULL != server); -+ assert(NULL != reason); -+ -+ /* debug */ -+ Debug((DEBUG_DEBUG, "split_add(\"%s\", \"%s\", \"%s\", \"%s\", %Tu, %Tu, %Tu, " -+ "%Tu, 0x%04x)", cli_name(cptr), cli_name(sptr), server, reason, -+ creation, expire, lastmod, lifetime, flags)); -+ -+ /* not adding SPLIT for server that is linked -+ * if sptr is my user throw error -+ * otherwise ignore - SERVER and SPLIT messages can cross, -+ * or a server is bursting and it will see our end and destroy the SPLITs -+ */ -+ if (FindServer(server)) { -+ if (MyUser(sptr)) -+ sendcmdto_one(&me, CMD_NOTICE, sptr, -+ "%C :SPLIT: Cannot add SPLIT %s - server is linked.", sptr, server); -+ return 0; -+ } -+ -+ /* -+ * You cannot set a negative (or zero) duration, nor can you set an -+ * duration greater than SPLIT_MAX_EXPIRE. -+ */ -+ if (expire - TStime() <= 0 || expire - TStime() > SPLIT_MAX_EXPIRE) { -+ if (MyUser(sptr)) -+ return send_reply(cptr, ERR_BADEXPIRE, expire - TStime()); -+ if (lifetime <= TStime()) /* no point going further */ -+ /* CHECK: sptr may have the wrong idea about the nettime? -+ * or we could be wrong? -+ * perhaps raise some sort of warning to ops -+ */ -+ return 0; -+ } -+ -+ /* empty reason */ -+ if (EmptyString(reason)) -+ ircd_snprintf(0, noreason, sizeof(noreason), "%C gave no reason.", sptr); -+ -+ /* lastmod is more than SPLIT_MAX_DRIFT seconds ahead of our idea of time -+ * correct and warn ops -+ */ -+ if (lastmod - TStime() > SPLIT_MAX_DRIFT) { -+ sendto_opmask_butone_ratelimited(0, SNO_NETWORK, &rate, -+ "Possible timestamp drift from %C; lastmod in SPLIT message is %is ahead of time", -+ IsServer(sptr) ? sptr : cli_user(sptr)->server, lastmod - TStime()); -+ lastmod = TStime() + SPLIT_MAX_DRIFT; -+ } -+ -+ /* make the split entry */ -+ split = split_make(server, EmptyString(reason) ? noreason : reason, -+ creation, expire, lastmod, lifetime, flags); -+ -+ /* got to have it now */ -+ assert(split); -+ -+ /* inform ops */ -+ sendto_opmask_butone(0, SNO_NETWORK, "%s adding%sSPLIT for %s, expiring at %Tu: %s", -+ (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ? -+ get_client_name_and_opername(sptr) : cli_name((cli_user(sptr))->server), -+ SplitIsActive(split) ? " " : " deactivated ", -+ split->sp_server, split->sp_expire, split->sp_reason); -+ -+ /* log it */ -+ log_write(LS_SPLIT, L_INFO, LOG_NOSNOTICE, -+ "%#C adding%sSPLIT for %s, expiring at %Tu: %s", -+ sptr, SplitIsActive(split) ? " " : " deactivated ", -+ split->sp_server, split->sp_expire, split->sp_reason); -+ -+ /* and propagate it */ -+ split_propagate(cptr, sptr, split, NULL); -+ -+ return 0; -+} -+ -+ -+/** Modify a split entry. -+ * @param[in] cptr Client that sent us the split modification. -+ * @param[in] sptr Client that originated the split modification. -+ * @param[in] split Split entry being modified. -+ * @param[in] action Resultant status of the SPLIT. -+ * @param[in] reason Reason. -+ * @param[in] expire Expiration time. -+ * @param[in] lastmod Last modification time. -+ * @param[in] lifetime Lifetime. -+ * @param[in] flags Bitwise combination of SPLIT_* flags. -+ * @return Zero. -+ */ -+int -+split_modify(struct Client *cptr, struct Client *sptr, struct Split *split, -+ enum SplitAction action, const char *reason, -+ time_t creation, time_t expire, time_t lastmod, time_t lifetime, -+ unsigned int flags) -+{ -+ char buf[BUFSIZE]; -+ char sp_reason[TOPICLEN+1]; -+ int pos = 0; -+ static time_t rate; -+ -+ assert(NULL != cptr); -+ assert(NULL != sptr); -+ assert(NULL != split); -+ -+ /* debug */ -+ Debug((DEBUG_DEBUG, "split_modify(cptr \"%s\", sptr \"%s\", split \"%s\", reason \"%s\"," -+ " action %d, creation %Tu, expire %Tu, lastmod %Tu, lifetime %Tu, flags 0x%04x)", -+ cli_name(cptr), cli_name(sptr), split->sp_server, reason, action, -+ creation, expire, lastmod, lifetime, flags)); -+ -+ /* not modifying SPLIT for server that is linked -+ * if sptr is my user throw error -+ * otherwise ignore - SERVER and SPLIT messages can cross. -+ * -+ * note: we cleanup SPLIT entries at end of burst, -+ * and not when a server is introduced. -+ * so between net junction and end of burst, -+ * we can get SPLITs for a linked server. -+ * also more than one server can be bursting at a time. -+ */ -+ if (FindServer(split->sp_server)) { -+ if (MyUser(sptr)) -+ sendcmdto_one(&me, CMD_NOTICE, sptr, -+ "%C :SPLIT: Cannot modify SPLIT %s - server is linked.", sptr, split->sp_server); -+ -+ /* SPLIT is not for a server part of a netmerge - free it */ -+ if (!SplitIsBurst(split)) -+ split_free(split); -+ return 0; -+ } -+ -+ /* check lastmod */ -+ /* check if my oper modifies the SPLIT -+ * in which case use the greater of lastmod and split->sp_lastmod+1 -+ * -+ * because if the lastmod of the split is in the future (greater than TStime()) -+ * my oper cannot modify it when we use TStime() as lastmod -+ * therefore use split->sp_lastmod+1 - ugly hack, but the only way in that situation -+ * to modify it, apart from force removing it first.. -+ */ -+ if (MyUser(sptr)) -+ lastmod = IRCD_MAX(lastmod, split->sp_lastmod + 1); -+ /* we have a more recent version */ -+ if (split->sp_lastmod > lastmod) { -+ /* middle of a burst, it will resync on its own */ -+ if (IsBurstOrBurstAck(cptr)) -+ return 0; -+ /* resync the server */ -+ return split_resend(cptr, split); -+ /* same version */ -+ } else if (split->sp_lastmod == lastmod) -+ return 0; -+ -+ /* lastmod is more than SPLIT_MAX_DRIFT seconds ahead of our idea of time -+ * correct and warn ops -+ * -+ * not in case it is my oper -+ * we use the lastmod of either TStime() or the lastmod we have plus 1 second -+ * see above -+ */ -+ if (lastmod - TStime() > SPLIT_MAX_DRIFT && !MyUser(sptr)) { -+ sendto_opmask_butone_ratelimited(0, SNO_NETWORK, &rate, -+ "Possible timestamp drift from %C; lastmod in SPLIT message is %is ahead of time", -+ IsServer(sptr) ? sptr : cli_user(sptr)->server, lastmod - TStime()); -+ lastmod = TStime() + SPLIT_MAX_DRIFT; -+ } -+ -+ /* we got here so there is a change of some sort */ -+ -+ /* check out the expiration time */ -+ if (flags & SPLIT_EXPIRE) { -+ if (expire != split->sp_expire) { -+ /* bad expiration time */ -+ if (MyUser(sptr) && (expire < TStime() || expire - TStime() > SPLIT_MAX_EXPIRE)) -+ return send_reply(sptr, ERR_BADEXPIRE, expire - TStime()); -+ /* expire timestamp is in the past, so remap to deactivate */ -+ if (expire < TStime() && action == SPLIT_ACTIVATE) -+ action = SPLIT_DEACTIVATE; -+ } else -+ flags &= ~SPLIT_EXPIRE; -+ } -+ -+ /* check out lifetime */ -+ if (!(flags & SPLIT_LIFETIME) || !lifetime) -+ lifetime = split->sp_lifetime; /* use Split lifetime */ -+ -+ /* raise lifetime when required */ -+ lifetime = IRCD_MAX(lifetime, expire); -+ -+ /* SPLIT already expired with this lifetime */ -+ if (lifetime - TStime() <= 0) -+ return 0; -+ -+ /* check if lifetime needs to be updated */ -+ if (lifetime > split->sp_lifetime) -+ flags |= SPLIT_LIFETIME; -+ else { -+ flags &= ~SPLIT_LIFETIME; -+ lifetime = 0; -+ } -+ -+ /* no changes to the reason - empty or the same */ -+ if ((flags & SPLIT_REASON) && -+ (EmptyString(reason) || !ircd_strcmp(split->sp_reason, reason))) -+ flags &= ~SPLIT_REASON; -+ -+ /* no status change -+ * activate but split is active -+ * deactivate but split is deactivated -+ * expire timestamp is in the past so it should be deactivated -+ * and cannot be activated anymore -+ */ -+ if ((action == SPLIT_ACTIVATE && SplitIsActive(split)) || -+ (action == SPLIT_DEACTIVATE && !SplitIsActive(split)) || -+ (IRCD_MAX(split->sp_expire, expire) <= TStime())) -+ action = SPLIT_MODIFY; -+ -+ /* debug */ -+ Debug((DEBUG_DEBUG, "About to perform changes; flags 0x%04x, action %s", -+ flags, action == SPLIT_ACTIVATE ? "SPLIT_ACTIVATE" : -+ (action == SPLIT_DEACTIVATE ? "SPLIT_DEACTIVATE" : -+ (action == SPLIT_MODIFY ? "SPLIT_MODIFY" : "")))); -+ -+ /* nothing to change at all */ -+ if (!(flags & SPLIT_UPDATE) && action == SPLIT_MODIFY) { -+ if (MyUser(sptr)) -+ sendcmdto_one(&me, CMD_NOTICE, sptr, -+ "%C :SPLIT: Cannot modify SPLIT %s - nothing to change.", sptr, split->sp_server); -+ return 0; -+ } -+ -+ /* update lastmod */ -+ split->sp_lastmod = lastmod; -+ -+ -+ /* activating split entry */ -+ if (action == SPLIT_ACTIVATE) { -+ split->sp_flags |= SPLIT_ACTIVE; -+ pos += ircd_snprintf(0, buf, sizeof(buf), " activating SPLIT"); -+ } -+ -+ /* deactivating split entry */ -+ if (action == SPLIT_DEACTIVATE) { -+ split->sp_flags &= ~SPLIT_ACTIVE; -+ pos += ircd_snprintf(0, buf, sizeof(buf), " deactivating SPLIT"); -+ } -+ -+ -+ /* update expire */ -+ if (flags & SPLIT_EXPIRE) { -+ split->sp_expire = expire; -+ if (pos < BUFSIZE) -+ pos += ircd_snprintf(0, buf + pos, sizeof(buf) - pos, -+ "%s%s changing expiration time to %Tu", -+ pos ? ";" : "", -+ pos && !(flags & (SPLIT_LIFETIME | SPLIT_REASON)) ? -+ " and" : "", expire); -+ } -+ -+ /* update lifetime */ -+ if (flags & SPLIT_LIFETIME) { -+ split->sp_lifetime = lifetime; -+ if (pos < BUFSIZE) -+ pos += ircd_snprintf(0, buf + pos, sizeof(buf) - pos, -+ "%s%s extending record lifetime to %Tu", -+ pos ? ";" : "", pos && !(flags & SPLIT_REASON) ? -+ " and" : "", lifetime); -+ } -+ -+ /* update reason */ -+ if (flags & SPLIT_REASON) { -+ MyFree(split->sp_reason); -+ ircd_strncpy(sp_reason, reason, TOPICLEN); -+ DupString(split->sp_reason, sp_reason); -+ if (pos < BUFSIZE) -+ pos += ircd_snprintf(0, buf + pos, sizeof(buf) - pos, -+ "%s%s changing reason to \"%s\"", -+ pos ? ";" : "", pos ? " and" : "", sp_reason); -+ } -+ -+ /* inform ops */ -+ sendto_opmask_butone(0, SNO_NETWORK, "%s modifying SPLIT for %s:%s", -+ (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ? -+ get_client_name_and_opername(sptr) : cli_name((cli_user(sptr))->server), -+ split->sp_server, buf); -+ -+ /* log it */ -+ log_write(LS_SPLIT, L_INFO, LOG_NOSNOTICE, -+ "%#C modifying SPLIT for %s:%s", -+ sptr, split->sp_server, buf); -+ -+ /* and propagate it */ -+ split_propagate(cptr, sptr, split, NULL); -+ -+ return 0; -+} -+ -+ -+/** Remove a split entry. -+ * @param[in] cptr Local client that sent us the split entry. -+ * @param[in] sptr Originator of the split entry. -+ * @param[in] split Split entry to remove. -+ * @param[in] reason Reason for removing this split entry. -+ * @return Zero. -+ */ -+int -+split_remove(struct Client *cptr, struct Client *sptr, struct Split *split, const char *reason) -+{ -+ assert(NULL != cptr); -+ assert(NULL != sptr); -+ assert(NULL != split); -+ assert(NULL != reason); -+ -+ /* debug */ -+ Debug((DEBUG_DEBUG, "split_remove(\"%s\", \"%s\", \"%s\", \"%s\")", -+ cli_name(cptr), cli_name(sptr), split->sp_server, reason)); -+ -+ /* deactivate entry and mark it for removal (used in split_propagate) */ -+ split->sp_flags |= SPLIT_REMOVING; -+ split->sp_flags &= ~SPLIT_ACTIVE; -+ -+ /* inform ops */ -+ sendto_opmask_butone(0, SNO_NETWORK, "%s removing SPLIT for %s, expiring at %Tu: %s (%s)", -+ (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ? -+ get_client_name_and_opername(sptr) : cli_name((cli_user(sptr))->server), -+ split->sp_server, split->sp_expire, split->sp_reason, reason); -+ -+ /* log it */ -+ log_write(LS_SPLIT, L_INFO, LOG_NOSNOTICE, -+ "%#C removing SPLIT for %s, expiring at %Tu: %s (%s)", -+ sptr, split->sp_server, split->sp_expire, split->sp_reason, reason); -+ -+ /* propagate it */ -+ split_propagate(cptr, sptr, split, reason); -+ -+ /* destroy it */ -+ split_free(split); -+ -+ return 0; -+} -+ -+ -+/** Find a split entry by name. -+ * @param[in] server Split entry name to search for. -+ * @return Matching split entry (or NULL if none match). -+ */ -+struct Split * -+split_find(char *server) -+{ -+ struct Split* split; -+ struct Split* ssplit; -+ -+ /* go over SPLITs */ -+ for (split = GlobalSplitList; split; split = ssplit) { -+ ssplit = split->sp_next; -+ -+ /* expire any that need expiring */ -+ if (split_expire(split)) -+ split_free(split); -+ -+ /* found it */ -+ else if (0 == ircd_strcmp(server, split->sp_server)) -+ return split; -+ } -+ -+ /* nothing found */ -+ return NULL; -+} -+ -+ -+/** Unlink and free an unused split entry. -+ * @param[in] split Server split entry to free. -+ */ -+void -+split_free(struct Split* split) -+{ -+ assert(NULL != split); -+ -+ /* squeeze this split entry out */ -+ *split->sp_prev_p = split->sp_next; -+ if (split->sp_next) -+ split->sp_next->sp_prev_p = split->sp_prev_p; -+ -+ /* and free up the memory */ -+ MyFree(split->sp_server); -+ MyFree(split->sp_reason); -+ MyFree(split); -+} -+ -+ -+/** Check whether a split entry has past its life time. -+ * when entry is active and past expire time, but not life time, deactivate it -+ * @param[in] split Server split entry to check. -+ * @return 1 when entry can be free'd, 0 otherwise. -+ */ -+int -+split_expire(struct Split* split) -+{ -+ assert(NULL != split); -+ -+ /* TODO: also check if the server in SPLIT entry is linked atm? */ -+ /* past lifetime */ -+ if (split->sp_lifetime <= TStime()) -+ return 1; -+ -+ /* past expire time, deactivate entry if it is active */ -+ if ((split->sp_expire <= TStime()) && SplitIsActive(split)) -+ split->sp_flags &= ~SPLIT_ACTIVE; -+ -+ return 0; -+} -+ -+ -+/** Send the full list of split entries to \a cptr. -+ * @param[in] cptr Local server to send split entries to. -+ */ -+void -+split_burst(struct Client *cptr) -+{ -+ struct Split *split; -+ struct Split *ssplit; -+ -+ assert(NULL != cptr); -+ -+ /* go over SPLITs */ -+ for (split = GlobalSplitList; split; split = ssplit) { -+ ssplit = split->sp_next; -+ -+ /* expire any that need expiring */ -+ if (split_expire(split)) { -+ split_free(split); -+ continue; -+ } -+ -+ /* if we have an entry for cptr, dont send it - but do not free here yet -+ * free it at end of burst, to get the correct count for SPLITs removed. -+ */ -+ if (ircd_strcmp(split->sp_server, cli_name(cptr)) == 0) -+ continue; -+ -+ /* send it */ -+ sendcmdto_one(&me, CMD_SPLIT, cptr, "%c%s %Tu %Tu %Tu %Tu :%s", -+ SplitIsActive(split) ? '+' : '-', split->sp_server, -+ split->sp_creation, split->sp_expire, -+ split->sp_lastmod, split->sp_lifetime, -+ split->sp_reason); -+ } -+} -+ -+ -+/** Forward a split to another server. -+ * @param[in] cptr Server to send split entries to. -+ * @param[in] split Split to forward. -+ * @return Zero. -+ */ -+int -+split_resend(struct Client *cptr, struct Split *split) -+{ -+ sendcmdto_one(&me, CMD_SPLIT, cptr, "%c%s %Tu %Tu %Tu %Tu :%s", -+ SplitIsActive(split) ? '+' : '-', split->sp_server, -+ split->sp_creation, split->sp_expire, -+ split->sp_lastmod, split->sp_lifetime, -+ split->sp_reason); -+ -+ return 0; -+} -+ -+ -+/** List split entries to a client. -+ * @param[in] sptr Client searching for split entries. -+ * @param[in] server Name of split entry to search for (if NULL, list all). -+ * @return Zero. -+ */ -+int -+split_list(struct Client *sptr, char *server) -+{ -+ struct Split *split; -+ int count = 0; -+ -+ assert(NULL != sptr); -+ -+ /* go through SPLITs */ -+ for (split = GlobalSplitList; split; split = split->sp_next) { -+ -+ /* expire any that need expiring */ -+ if (split_expire(split)) { -+ split_free(split); -+ continue; -+ } -+ -+ /* server given and does not match */ -+ if (server && match(server, split->sp_server)) -+ continue; -+ -+ /* got one */ -+ count++; -+ send_reply(sptr, RPL_SPLITLIST, split->sp_server, -+ split->sp_creation, split->sp_expire, split->sp_lastmod, split->sp_lifetime, -+ SplitIsActive(split) ? '+' : '-', split->sp_reason); -+ } -+ -+ /* server given and nothing found */ -+ if (server && !count) -+ return send_reply(sptr, ERR_NOSUCHSPLIT, server); -+ -+ /* end of splitlist information */ -+ return send_reply(sptr, RPL_ENDOFSPLITLIST); -+} -+ -+ -+/** Mark SPLIT for new server with SPLIT_BURST -+ * @param[in] acptr Server introduced to the network -+ */ -+void -+split_newserver(struct Client *acptr) -+{ -+ struct Split *split; -+ -+ assert(NULL != acptr); -+ -+ /* debug */ -+ Debug((DEBUG_DEBUG, "split_newserver(\"%s\")", cli_name(acptr))); -+ -+ /* mark the SPLIT with SPLIT_BURST -+ * so we know this SPLIT is marked for removal already -+ * but not remove it just yet to get the correct count -+ * of SPLITs removed at the end of burst. -+ * -+ * also we need the SPLIT in case the net breaks again -+ * before end of burst? -+ */ -+ if ((split = split_find(cli_name(acptr)))) -+ split->sp_flags |= SPLIT_BURST; -+} -+ -+ -+/** Auto destroy SPLITs for servers gained in a netmerge -+ * @param[in] sptr Server that has linked to the network -+ * @return Number of destroyed SPLITs -+ */ -+int -+split_netmerge(struct Client *sptr) -+{ -+ struct DLink *lp; -+ struct Split *split; -+ int count = 0; -+ -+ assert(NULL != sptr); -+ -+ /* debug */ -+ Debug((DEBUG_DEBUG, "split_netmerge(\"%s\")", cli_name(sptr))); -+ -+ /* find the SPLIT for this server */ -+ if ((split = split_find(cli_name(sptr)))) { -+ split_free(split); -+ count++; -+ } -+ -+ /* go over its downlinks */ -+ for (lp = cli_serv(sptr)->down; lp; lp = lp->next) -+ count += split_netmerge(lp->value.cptr); -+ -+ /* return the number of SPLITs removed */ -+ return count; -+} -+ -+ -+/** Auto create SPLITs for servers lost in a netbreak -+ * @param[in] victim Server that lost link to network -+ * @param[in] reason Reason to add to SPLITs -+ * @return Number of created SPLITs -+ */ -+int -+split_netbreak(struct Client *victim, const char *reason) -+{ -+ struct DLink *lp; -+ struct Split *split; -+ int count = 0; -+ time_t creation = TStime(), expire = TStime() + feature_int(FEAT_SPLIT_AUTO_EXPIRE), -+ lastmod = TStime(), lifetime = expire; -+ unsigned int flags = SPLIT_ACTIVE; -+ -+ assert(NULL != victim); -+ -+ /* debug */ -+ Debug((DEBUG_DEBUG, "split_netbreak(\"%s\", \"%s\")", cli_name(victim), reason)); -+ -+ /* bad auto expire value */ -+ if (feature_int(FEAT_SPLIT_AUTO_EXPIRE) <= 0) -+ return 0; -+ -+ /* TODO: what if we do have a SPLIT for this server? -+ * we remove splits in end of burst -+ * and if the netbreaks again before that -+ * free the SPLIT and create a new one? -+ * or simply update lastmod/lifetime/reason but leave the status? -+ */ -+ /* find the SPLIT for this server */ -+ if (!(split = split_find(cli_name(victim)))) { -+ split_make(cli_name(victim), reason, creation, expire, lastmod, lifetime, flags); -+ count++; -+ } else -+ /* clear the burst flag for it */ -+ split->sp_flags &= SPLIT_BURST; -+ -+ /* go over its downlinks */ -+ for (lp = cli_serv(victim)->down; lp; lp = lp->next) -+ count += split_netbreak(lp->value.cptr, reason); -+ -+ /* return the number of SPLITs created */ -+ return count; -+} -+ -+ -+/** Auto create SPLITs for servers we have a Connect Block for -+ * -+ */ -+void -+split_conf() -+{ -+ struct ConfItem *conf; -+ struct Split *split; -+ time_t creation = TStime(), expire = TStime() + feature_int(FEAT_SPLIT_AUTO_EXPIRE), -+ lastmod = TStime(), lifetime = expire; -+ unsigned int flags = SPLIT_ACTIVE; -+ char reason[BUFSIZE]; -+ -+ /* debug */ -+ Debug((DEBUG_DEBUG, "split_conf()")); -+ -+ /* we are not set to generate SPLITs */ -+ if (!feature_bool(FEAT_SPLIT)) -+ return; -+ -+ /* TODO: log this problem? */ -+ /* bad auto expire value */ -+ if (feature_int(FEAT_SPLIT_AUTO_EXPIRE) <= 0) -+ return; -+ -+ ircd_snprintf(0, reason, sizeof(reason), -+ "Generated upon loading conf file on %C", &me); -+ -+ /* go over the conf contents */ -+ for (conf = GlobalConfList; conf; conf = conf->next) { -+ -+ /* not a Connect Block */ -+ if (CONF_SERVER != conf->status) -+ continue; -+ -+ /* server is linked */ -+ if (FindServer(conf->name)) -+ continue; -+ -+ /* we have a SPLIT for this server already */ -+ if (split_find(conf->name)) -+ continue; -+ -+ /* TODO: use SNO_OLDSNO here? -+ * just like nickcollisions on local users go there? -+ * or at least change the source / message format? -+ * /REHASH goes to SNO_OLDSNO? so this too? -+ * if oper did rehash, add his name here? -+ */ -+ /* inform ops */ -+ sendto_opmask_butone(0, SNO_NETWORK, "%C adding SPLIT for %s, expiring at %Tu: %s", -+ &me, conf->name, expire, reason); -+ -+ /* log it */ -+ log_write(LS_SPLIT, L_INFO, LOG_NOSNOTICE, -+ "%C adding SPLIT for %s, expiring at %Tu: %s", -+ &me, conf->name, expire, reason); -+ -+ /* make the split entry */ -+ split = split_make(conf->name, reason, creation, expire, lastmod, lifetime, flags); -+ -+ /* got to have it now */ -+ assert(split); -+ -+ /* and propagate it */ -+ split_propagate(&me, &me, split, NULL); -+ } -+} -+ -+ -+/** Statistics callback to list SPLITs. -+ * @param[in] sptr Client requesting statistics. -+ * @param[in] sd Stats descriptor for request (ignored). -+ * @param[in] param Extra parameter from user (ignored). -+ */ -+void -+split_stats(struct Client *sptr, const struct StatDesc *sd, char *param) -+{ -+ struct Split *split; -+ -+ /* send header so the client knows what we are showing */ -+ send_reply(sptr, SND_EXPLICIT | RPL_STATSHEADER, -+ "S Server Creation Expire Lastmod Lifetime Status :Reason"); -+ -+ /* go over SPLIT entries */ -+ for (split = GlobalSplitList; split; split = split->sp_next) { -+ -+ /* does not match */ -+ if (param && match(param, split->sp_server)) -+ continue; -+ -+ /* send it */ -+ send_reply(sptr, RPL_STATSSPLIT, split->sp_server, -+ split->sp_creation, split->sp_expire, split->sp_lastmod, split->sp_lifetime, -+ SplitIsActive(split) ? '+' : '-', split->sp_reason); -+ } -+} -+ -+ -+/** Count split entries and memory used by them. -+ * @param[out] sp_size Receives total number of bytes allocated for split entries. -+ * @return Number of split entries currently allocated. -+ */ -+int -+split_memory_count(size_t *sp_size) -+{ -+ struct Split *split; -+ unsigned int sp = 0; -+ -+ for (split = GlobalSplitList; split; split = split->sp_next) { -+ sp++; -+ *sp_size += sizeof(struct Split); -+ *sp_size += split->sp_server ? (strlen(split->sp_server) + 1) : 0; -+ *sp_size += split->sp_reason ? (strlen(split->sp_reason) + 1) : 0; -+ } -+ return sp; -+}