]> jfr.im git - irc/quakenet/snircd-patchqueue.git/commitdiff
Removed split.patch
authorwiebe <redacted>
Wed, 17 Mar 2010 12:43:23 +0000 (13:43 +0100)
committerwiebe <redacted>
Wed, 17 Mar 2010 12:43:23 +0000 (13:43 +0100)
series
split.patch [deleted file]

diff --git a/series b/series
index c9675886c7a9d400d1bf9cbe383cb079f32156d2..8d32adda33cf38dd9cd304cc98155885f0cd6989 100644 (file)
--- 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 (file)
index 4f9b180..0000000
+++ /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>
- 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 <klmitch@mit.edu>
-+ *
-+ * 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 <sys/types.h>
-+#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 <num> sizespec
- %type <num> 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 <assert.h> -- 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 <assert.h> -- Now using assert in ircd_log.h */
- #include <stdlib.h>
-@@ -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 <assert.h> -- 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 <klmitch@mit.edu>
-+ *
-+ * 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 <assert.h> -- Now using assert in ircd_log.h */
-+#include <stdlib.h>
-+#include <string.h>
-+
-+/*
-+ * ms_split - server message handler
-+ *
-+ * parv[0] = Send prefix
-+ * parv[1] = (+|-)<server name>
-+ * 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] = [+|-]<server name>
-+ * 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] = [<server name>]
-+ *
-+ */
-+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 <klmitch@mit.edu>
-+ *
-+ * 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 <assert.h> -- Now using assert in ircd_log.h */
-+#include <string.h>
-+
-+/** 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" : "<UNKNOWN>"))));
-+
-+  /* 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;
-+}