- The big forward port. I probably broke lots of stuff, so please look over any
authorAndrew Miller <a1kmm@amxl.com>
Tue, 7 Jan 2003 10:06:45 +0000 (10:06 +0000)
committerAndrew Miller <a1kmm@amxl.com>
Tue, 7 Jan 2003 10:06:45 +0000 (10:06 +0000)
  changes you made to .11 and make sure they are forward ported correctly. A lot
  of the ircd was changed.

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@896 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

97 files changed:
include/channel.h
include/class.h
include/client.h
include/gline.h
include/handlers.h
include/ircd.h
include/ircd_features.h
include/listener.h
include/motd.h
include/msg.h
include/msgq.h
include/numeric.h
include/opercmds.h
include/s_conf.h
include/s_debug.h
include/s_misc.h
include/s_stats.h
include/s_user.h
include/send.h
include/struct.h
include/supported.h
include/userload.h
include/whocmds.h
ircd/IPcheck.c
ircd/Makefile.in
ircd/channel.c
ircd/class.c
ircd/client.c
ircd/gline.c
ircd/ircd.c
ircd/ircd_features.c
ircd/ircd_lexer.l
ircd/ircd_log.c
ircd/ircd_parser.y
ircd/ircd_relay.c
ircd/ircd_snprintf.c
ircd/jupe.c
ircd/list.c
ircd/listener.c
ircd/m_account.c
ircd/m_admin.c
ircd/m_asll.c [new file with mode: 0644]
ircd/m_away.c
ircd/m_burst.c
ircd/m_clearmode.c
ircd/m_create.c
ircd/m_gline.c
ircd/m_invite.c
ircd/m_join.c
ircd/m_kick.c
ircd/m_kill.c
ircd/m_links.c
ircd/m_lusers.c
ircd/m_map.c
ircd/m_mode.c
ircd/m_motd.c
ircd/m_names.c
ircd/m_nick.c
ircd/m_notice.c
ircd/m_oper.c
ircd/m_opmode.c
ircd/m_part.c
ircd/m_ping.c
ircd/m_pong.c
ircd/m_privmsg.c
ircd/m_server.c
ircd/m_settime.c
ircd/m_squit.c
ircd/m_stats.c
ircd/m_time.c
ircd/m_topic.c
ircd/m_trace.c
ircd/m_version.c
ircd/m_wallchops.c
ircd/m_wallvoices.c [new file with mode: 0644]
ircd/m_who.c
ircd/m_whois.c
ircd/m_whowas.c
ircd/map.c
ircd/motd.c
ircd/msgq.c
ircd/numnicks.c
ircd/opercmds.c
ircd/parse.c
ircd/random.c
ircd/s_auth.c
ircd/s_bsd.c
ircd/s_conf.c
ircd/s_debug.c
ircd/s_err.c
ircd/s_misc.c
ircd/s_numeric.c
ircd/s_stats.c
ircd/s_user.c
ircd/send.c
ircd/userload.c
ircd/whocmds.c

index ff39e43cebc820e56097e9da27f96434b1d82f44..d12072c6b4489b57dbe28cb2208cd9ddb7d62588 100644 (file)
@@ -113,9 +113,8 @@ struct Client;
 #define is_listed(x)            ((x)->mode.mode & MODE_LISTED)
 
 #define IsLocalChannel(name)    (*(name) == '&')
-#define IsModelessChannel(name) (*(name) == '+')
 #define IsChannelName(name)     (*(name) == '#' || \
-                                IsModelessChannel(name) || IsLocalChannel(name))
+                                IsLocalChannel(name))
 
 typedef enum ChannelGetType {
   CGT_NO_CREATE,
index 0e197461b8bd77663ef39b40e6fc1dde8143bdbb..df53e164d224bd70116fe003d79bf93047fbeda7 100644 (file)
@@ -28,6 +28,7 @@
 
 struct Client;
 struct ConfItem;
+struct StatDesc;
 
 /*
  * Structures
@@ -81,7 +82,8 @@ extern char *get_client_class(struct Client *acptr);
 extern void add_class(char *name, unsigned int ping,
                       unsigned int confreq, unsigned int maxli, unsigned int sendq);
 extern void check_class(void);
-extern void report_classes(struct Client *sptr);
+extern void report_classes(struct Client *sptr, struct StatDesc *sd, int stat,
+                           char *param);
 extern unsigned int get_sendq(struct Client* cptr);
 
 extern void class_send_meminfo(struct Client* cptr);
index 3522c40ee3efb7f0cb8bbc45a87f878bfff7dbe5..4d61472e7f12c13f0f0598773c828b2ccb6b879a 100644 (file)
@@ -66,51 +66,99 @@ struct AuthRequest;
  * source file, or in the source file itself (when only used in that file).
  */
 
-#define PRIV_CHAN_LIMIT                 1 /* no channel limit on oper */
-#define PRIV_MODE_LCHAN                 2 /* oper can mode local chans */
-#define PRIV_WALK_LCHAN                 3 /* oper can walk thru local modes */
-#define PRIV_DEOP_LCHAN                 4 /* no deop oper on local chans */
-#define PRIV_SHOW_INVIS                 5 /* show local invisible users */
-#define PRIV_SHOW_ALL_INVIS     6 /* show all invisible users */
-#define PRIV_UNLIMIT_QUERY      7 /* unlimit who queries */
-
-#define PRIV_KILL               8 /* oper can KILL */
-#define PRIV_LOCAL_KILL                 9 /* oper can local KILL */
-#define PRIV_REHASH            10 /* oper can REHASH */
-#define PRIV_RESTART           11 /* oper can RESTART */
-#define PRIV_DIE               12 /* oper can DIE */
-#define PRIV_GLINE             13 /* oper can GLINE */
-#define PRIV_LOCAL_GLINE       14 /* oper can local GLINE */
-#define PRIV_JUPE              15 /* oper can JUPE */
-#define PRIV_LOCAL_JUPE                16 /* oper can local JUPE */
-#define PRIV_OPMODE            17 /* oper can OP/CLEARMODE */
-#define PRIV_LOCAL_OPMODE      18 /* oper can local OP/CLEARMODE */
-#define PRIV_SET               19 /* oper can SET */
-#define PRIV_WHOX              20 /* oper can use /who x */
-#define PRIV_BADCHAN           21 /* oper can BADCHAN */
-#define PRIV_LOCAL_BADCHAN     22 /* oper can local BADCHAN */
-#define PRIV_SEE_CHAN          23 /* oper can see in secret chans */
-
-#define PRIV_PROPAGATE         24 /* propagate oper status */
-#define PRIV_DISPLAY           25 /* "Is an oper" displayed */
-#define PRIV_SEE_OPERS         26 /* display hidden opers */
-
-#define PRIV_WIDE_GLINE                27 /* oper can set wider G-lines */
-
-#define PRIV_LIST_CHAN          28 /* oper can list secret channels */
-
-#define PRIV_LAST_PRIV         28 /* must be the same as the last priv */
-
-#define _PRIV_NBITS            (8 * sizeof(unsigned long))
-
-#define _PRIV_IDX(priv)                ((priv) / _PRIV_NBITS)
-#define _PRIV_BIT(priv)                (1 << ((priv) % _PRIV_NBITS))
-
-struct Privs {
-  unsigned long priv_mask[(PRIV_LAST_PRIV / _PRIV_NBITS) + 1];
-};
-
-struct Connection {
+typedef unsigned long flagpage_t;
+
+#define FLAGSET_NBITS (8 * sizeof(flagpage_t))
+#define FLAGSET_INDEX(flag) (flag / FLAGSET_NBITS)
+#define FLAGSET_MASK(flag) (1<<(flag % FLAGSET_NBITS))
+
+#define DECLARE_FLAGSET(name,max) \
+  struct name \
+  { \
+    unsigned long bits[((max + FLAGSET_NBITS - 1) / FLAGSET_NBITS)]; \
+  };
+
+#define FLAGSET_ISSET(set,flag) ((set).bits[FLAGSET_INDEX(flag)] & FLAGSET_MASK(flag))
+#define FLAGSET_SET(set, flag) (set).bits[FLAGSET_INDEX(flag)] |= FLAGSET_MASK(flag)
+#define FLAGSET_CLEAR(set, flag) (set).bits[FLAGSET_INDEX(flag)] &= ~FLAGSET_MASK(flag)
+
+enum Priv
+  {
+    PRIV_CHAN_LIMIT, /* no channel limit on oper */
+    PRIV_MODE_LCHAN, /* oper can mode local chans */
+    PRIV_WALK_LCHAN, /* oper can walk thru local modes */
+    PRIV_DEOP_LCHAN, /* no deop oper on local chans */
+    PRIV_SHOW_INVIS, /* show local invisible users */
+    PRIV_SHOW_ALL_INVIS, /* show all invisible users */
+    PRIV_UNLIMIT_QUERY, /* unlimit who queries */
+    PRIV_KILL, /* oper can KILL */
+    PRIV_LOCAL_KILL, /* oper can local KILL */
+    PRIV_REHASH, /* oper can REHASH */
+    PRIV_RESTART, /* oper can RESTART */
+    PRIV_DIE, /* oper can DIE */
+    PRIV_GLINE, /* oper can GLINE */
+    PRIV_LOCAL_GLINE, /* oper can local GLINE */
+    PRIV_JUPE, /* oper can JUPE */
+    PRIV_LOCAL_JUPE, /* oper can local JUPE */
+    PRIV_OPMODE, /* oper can OP/CLEARMODE */
+    PRIV_LOCAL_OPMODE, /* oper can local OP/CLEARMODE */
+    PRIV_SET,  /* oper can SET */
+    PRIV_WHOX, /* oper can use /who x */
+    PRIV_BADCHAN, /* oper can BADCHAN */
+    PRIV_LOCAL_BADCHAN, /* oper can local BADCHAN */
+    PRIV_SEE_CHAN, /* oper can see in secret chans */
+    PRIV_PROPAGATE, /* propagate oper status */
+    PRIV_DISPLAY, /* "Is an oper" displayed */
+    PRIV_SEE_OPERS, /* display hidden opers */
+    PRIV_WIDE_GLINE, /* oper can set wider G-lines */
+    PRIV_LIST_CHAN, /* oper can list secret channels */
+    PRIV_FORCE_OPMODE,
+    PRIV_FORCE_LOCAL_OPMODE,
+    PRIV_LAST_PRIV /* must be the same as the last priv */
+  };
+
+enum Flag
+  {
+    FLAG_PINGSENT,                  /* Unreplied ping sent */
+    FLAG_DEADSOCKET,                /* Local socket is dead--Exiting soon */
+    FLAG_KILLED,                    /* Prevents "QUIT" from being sent for this */
+    FLAG_BLOCKED,                   /* socket is in a blocked condition */
+    FLAG_CLOSING,                   /* set when closing to suppress errors */
+    FLAG_UPING,                     /* has active UDP ping request */
+    FLAG_CHKACCESS,                 /* ok to check clients access if set */
+    FLAG_HUB,                       /* server is a hub */
+    FLAG_SERVICE,                   /* server is a service */
+    FLAG_LOCAL,                     /* set for local clients */
+    FLAG_GOTID,                     /* successful ident lookup achieved */
+    FLAG_DOID,                      /* I-lines say must use ident return */
+    FLAG_NONL,                      /* No \n in buffer */
+    FLAG_TS8,                       /* Why do you want to know? */
+    FLAG_MAP,                       /* Show server on the map */
+    FLAG_JUNCTION,                  /* Junction causing the net.burst */
+    FLAG_BURST,                     /* Server is receiving a net.burst */
+    FLAG_BURST_ACK,                 /* Server is waiting for eob ack */
+    FLAG_IPCHECK,                   /* Added or updated IPregistry data */
+    FLAG_LOCOP,                     /* Local operator -- SRB */
+    FLAG_SERVNOTICE,                /* server notices such as kill */
+    FLAG_OPER,                      /* Operator */
+    FLAG_INVISIBLE,                 /* makes user invisible */
+    FLAG_WALLOP,                    /* send wallops to them */
+    FLAG_DEAF,                      /* Makes user deaf */
+    FLAG_CHSERV,                    /* Disallow KICK or MODE -o on the user;
+                                       don't display channels in /whois */
+    FLAG_DEBUG,                     /* send global debug/anti-hack info */
+    FLAG_ACCOUNT,                   /* account name has been set */
+    FLAG_HIDDENHOST,                /* user's host is hidden */
+    FLAG_LAST_FLAG,
+    FLAG_LOCAL_UMODES = FLAG_LOCOP, /* First local mode flag */
+    FLAG_GLOBAL_UMODES = FLAG_OPER  /* First global mode flag */
+  };
+
+DECLARE_FLAGSET(Privs, PRIV_LAST_PRIV);
+DECLARE_FLAGSET(Flags, FLAG_LAST_FLAG);
+
+struct Connection
+{
   /*
    *  The following fields are allocated only for local clients
    *  (directly connected to *this* server with a socket.
@@ -187,7 +235,7 @@ struct Client {
   time_t         cli_firsttime; /* time client was created */
   time_t         cli_lastnick;  /* TimeStamp on nick */
   int            cli_marker;    /* /who processing marker */
-  unsigned int   cli_flags;     /* client flags */
+  struct Flags   cli_flags;     /* client flags */
   unsigned int   cli_hopcount;  /* number of servers to this 0 = local */
   struct in_addr cli_ip;        /* Real ip# NOT defined for remote servers! */
   short          cli_status;    /* Client type */
@@ -346,110 +394,81 @@ struct Client {
             (STAT_SERVER | STAT_CONNECTING | STAT_HANDSHAKE))
 
 /*
- * FLAGS macros
- */
-#define FLAGS_PINGSENT   0x0001 /* Unreplied ping sent */
-#define FLAGS_DEADSOCKET 0x0002 /* Local socket is dead--Exiting soon */
-#define FLAGS_KILLED     0x0004 /* Prevents "QUIT" from being sent for this */
-#define FLAGS_OPER       0x0008 /* Operator */
-#define FLAGS_LOCOP      0x0010 /* Local operator -- SRB */
-#define FLAGS_INVISIBLE  0x0020 /* makes user invisible */
-#define FLAGS_WALLOP     0x0040 /* send wallops to them */
-#define FLAGS_SERVNOTICE 0x0080 /* server notices such as kill */
-#define FLAGS_BLOCKED    0x0100 /* socket is in a blocked condition */
-#define FLAGS_ACCOUNT    0x0200 /* account name has been set */
-#define FLAGS_CLOSING    0x0400 /* set when closing to suppress errors */
-#define FLAGS_UPING      0x0800 /* has active UDP ping request */
-#define FLAGS_CHKACCESS  0x1000 /* ok to check clients access if set */
-#define FLAGS_HUB        0x2000 /* server is a hub */
-#define FLAGS_SERVICE    0x4000 /* server is a service */
-#define FLAGS_HIDDENHOST 0x8000 /* user's host is hidden */
-#define FLAGS_LOCAL     0x00010000      /* set for local clients */
-#define FLAGS_GOTID     0x00020000      /* successful ident lookup achieved */
-#define FLAGS_DOID      0x00040000      /* I-lines say must use ident return */
-#define FLAGS_NONL      0x00080000      /* No \n in buffer */
-#define FLAGS_TS8       0x00100000      /* Why do you want to know? */
-#define FLAGS_MAP       0x00800000      /* Show server on the map */
-#define FLAGS_JUNCTION  0x01000000      /* Junction causing the net.burst */
-#define FLAGS_DEAF      0x02000000      /* Makes user deaf */
-#define FLAGS_CHSERV    0x04000000      /* Disallow KICK or MODE -o on the user;
-                                           don't display channels in /whois */
-#define FLAGS_BURST     0x08000000      /* Server is receiving a net.burst */
-#define FLAGS_BURST_ACK 0x10000000      /* Server is waiting for eob ack */
-#define FLAGS_DEBUG     0x20000000      /* send global debug/anti-hack info */
-#define FLAGS_IPCHECK   0x40000000      /* Added or updated IPregistry data */
-
-#define SEND_UMODES \
-    (FLAGS_INVISIBLE|FLAGS_OPER|FLAGS_WALLOP|FLAGS_DEAF|FLAGS_CHSERV|FLAGS_DEBUG|FLAGS_ACCOUNT|FLAGS_HIDDENHOST)
-#define ALL_UMODES (SEND_UMODES|FLAGS_SERVNOTICE|FLAGS_LOCOP)
-#define FLAGS_ID (FLAGS_DOID|FLAGS_GOTID)
-
-/*
- * flags macros.
+ * flags macros
  */
-#define DoAccess(x)             (cli_flags(x) & FLAGS_CHKACCESS)
-#define IsAnOper(x)             (cli_flags(x) & (FLAGS_OPER|FLAGS_LOCOP))
-#define IsBlocked(x)            (cli_flags(x) & FLAGS_BLOCKED)
-#define IsBurst(x)              (cli_flags(x) & FLAGS_BURST)
-#define IsBurstAck(x)           (cli_flags(x) & FLAGS_BURST_ACK)
-#define IsBurstOrBurstAck(x)    (cli_flags(x) & (FLAGS_BURST|FLAGS_BURST_ACK))
-#define IsChannelService(x)     (cli_flags(x) & FLAGS_CHSERV)
-#define IsDead(x)               (cli_flags(x) & FLAGS_DEADSOCKET)
-#define IsDeaf(x)               (cli_flags(x) & FLAGS_DEAF)
-#define IsIPChecked(x)          (cli_flags(x) & FLAGS_IPCHECK)
-#define IsIdented(x)            (cli_flags(x) & FLAGS_GOTID)
-#define IsInvisible(x)          (cli_flags(x) & FLAGS_INVISIBLE)
-#define IsJunction(x)           (cli_flags(x) & FLAGS_JUNCTION)
-#define IsLocOp(x)              (cli_flags(x) & FLAGS_LOCOP)
-#define IsLocal(x)              (cli_flags(x) & FLAGS_LOCAL)
-#define IsOper(x)               (cli_flags(x) & FLAGS_OPER)
-#define IsUPing(x)              (cli_flags(x) & FLAGS_UPING)
-#define NoNewLine(x)            (cli_flags(x) & FLAGS_NONL)
-#define SendDebug(x)            (cli_flags(x) & FLAGS_DEBUG)
-#define SendServNotice(x)       (cli_flags(x) & FLAGS_SERVNOTICE)
-#define SendWallops(x)          (cli_flags(x) & FLAGS_WALLOP)
-#define IsHub(x)                (cli_flags(x) & FLAGS_HUB)
-#define IsService(x)            (cli_flags(x) & FLAGS_SERVICE)
-#define IsAccount(x)            (cli_flags(x) & FLAGS_ACCOUNT)
-#define IsHiddenHost(x)                (cli_flags(x) & FLAGS_HIDDENHOST)
-#define HasHiddenHost(x)       (IsAccount(x) && IsHiddenHost(x))
+#define FlagSet(fset, flag) FLAGSET_SET(*fset, flag)
+#define FlagClr(fset, flag) FLAGSET_CLEAR(*fset, flag)
+#define FlagHas(fset, flag) FLAGSET_ISSET(*fset, flag)
+#define SetFlag(cli, flag)      FlagSet(&cli_flags(cli), flag)
+#define ClrFlag(cli, flag)      FlagClr(&cli_flags(cli), flag)
+#define HasFlag(cli, flag)      FlagHas(&cli_flags(cli), flag)
+
+#define DoAccess(x)             HasFlag(x, FLAG_CHKACCESS)
+#define IsAnOper(x)             (HasFlag(x, FLAG_OPER) || HasFlag(x, FLAG_LOCOP))
+#define IsBlocked(x)            HasFlag(x, FLAG_BLOCKED)
+#define IsBurst(x)              HasFlag(x, FLAG_BURST)
+#define IsBurstAck(x)           HasFlag(x, FLAG_BURST_ACK)
+#define IsBurstOrBurstAck(x)    (HasFlag(x, FLAG_BURST) || HasFlag(x, FLAG_BURST_ACK))
+#define IsChannelService(x)     HasFlag(x, FLAG_CHSERV)
+#define IsDead(x)               HasFlag(x, FLAG_DEADSOCKET)
+#define IsDeaf(x)               HasFlag(x, FLAG_DEAF)
+#define IsIPChecked(x)          HasFlag(x, FLAG_IPCHECK)
+#define IsIdented(x)            HasFlag(x, FLAG_GOTID)
+#define IsInvisible(x)          HasFlag(x, FLAG_INVISIBLE)
+#define IsJunction(x)           HasFlag(x, FLAG_JUNCTION)
+#define IsLocOp(x)              HasFlag(x, FLAG_LOCOP)
+#define IsLocal(x)              HasFlag(x, FLAG_LOCAL)
+#define IsOper(x)               HasFlag(x, FLAG_OPER)
+#define IsUPing(x)              HasFlag(x, FLAG_UPING)
+#define NoNewLine(x)            HasFlag(x, FLAG_NONL)
+#define SendDebug(x)            HasFlag(x, FLAG_DEBUG)
+#define SendServNotice(x)       HasFlag(x, FLAG_SERVNOTICE)
+#define SendWallops(x)          HasFlag(x, FLAG_WALLOP)
+#define IsHub(x)                HasFlag(x, FLAG_HUB)
+#define IsService(x)            HasFlag(x, FLAG_SERVICE)
+#define IsAccount(x)            HasFlag(x, FLAG_ACCOUNT)
+#define IsHiddenHost(x)         HasFlag(x, FLAG_HIDDENHOST)
+#define IsPingSent(x)           HasFlag(x, FLAG_PINGSENT)
 
 #define IsPrivileged(x)         (IsAnOper(x) || IsServer(x))
-
-#define SetAccess(x)            (cli_flags(x) |= FLAGS_CHKACCESS)
-#define SetBurst(x)             (cli_flags(x) |= FLAGS_BURST)
-#define SetBurstAck(x)          (cli_flags(x) |= FLAGS_BURST_ACK)
-#define SetChannelService(x)    (cli_flags(x) |= FLAGS_CHSERV)
-#define SetDeaf(x)              (cli_flags(x) |= FLAGS_DEAF)
-#define SetDebug(x)             (cli_flags(x) |= FLAGS_DEBUG)
-#define SetGotId(x)             (cli_flags(x) |= FLAGS_GOTID)
-#define SetIPChecked(x)         (cli_flags(x) |= FLAGS_IPCHECK)
-#define SetInvisible(x)         (cli_flags(x) |= FLAGS_INVISIBLE)
-#define SetJunction(x)          (cli_flags(x) |= FLAGS_JUNCTION)
-#define SetLocOp(x)             (cli_flags(x) |= FLAGS_LOCOP)
-#define SetOper(x)              (cli_flags(x) |= FLAGS_OPER)
-#define SetUPing(x)             (cli_flags(x) |= FLAGS_UPING)
-#define SetWallops(x)           (cli_flags(x) |= FLAGS_WALLOP)
-#define SetServNotice(x)        (cli_flags(x) |= FLAGS_SERVNOTICE)
-#define SetHub(x)               (cli_flags(x) |= FLAGS_HUB)
-#define SetService(x)           (cli_flags(x) |= FLAGS_SERVICE)
-#define SetAccount(x)           (cli_flags(x) |= FLAGS_ACCOUNT)
-#define SetHiddenHost(x)       (cli_flags(x) |= FLAGS_HIDDENHOST)
-
-#define ClearAccess(x)          (cli_flags(x) &= ~FLAGS_CHKACCESS)
-#define ClearBurst(x)           (cli_flags(x) &= ~FLAGS_BURST)
-#define ClearBurstAck(x)        (cli_flags(x) &= ~FLAGS_BURST_ACK)
-#define ClearChannelService(x)  (cli_flags(x) &= ~FLAGS_CHSERV)
-#define ClearDeaf(x)            (cli_flags(x) &= ~FLAGS_DEAF)
-#define ClearDebug(x)           (cli_flags(x) &= ~FLAGS_DEBUG)
-#define ClearIPChecked(x)       (cli_flags(x) &= ~FLAGS_IPCHECK)
-#define ClearInvisible(x)       (cli_flags(x) &= ~FLAGS_INVISIBLE)
-#define ClearLocOp(x)           (cli_flags(x) &= ~FLAGS_LOCOP)
-#define ClearOper(x)            (cli_flags(x) &= ~FLAGS_OPER)
-#define ClearUPing(x)           (cli_flags(x) &= ~FLAGS_UPING)
-#define ClearWallops(x)         (cli_flags(x) &= ~FLAGS_WALLOP)
-#define ClearServNotice(x)      (cli_flags(x) &= ~FLAGS_SERVNOTICE)
-#define ClearHiddenHost(x)     (cli_flags(x) &= ~FLAGS_HIDDENHOST)
+#define HasHiddenHost(x)        (IsHiddenHost(x) && IsAccount(x))
+
+#define SetAccess(x)            SetFlag(x, FLAG_CHKACCESS)
+#define SetBurst(x)             SetFlag(x, FLAG_BURST)
+#define SetBurstAck(x)          SetFlag(x, FLAG_BURST_ACK)
+#define SetChannelService(x)    SetFlag(x, FLAG_CHSERV)
+#define SetDeaf(x)              SetFlag(x, FLAG_DEAF)
+#define SetDebug(x)             SetFlag(x, FLAG_DEBUG)
+#define SetGotId(x)             SetFlag(x, FLAG_GOTID)
+#define SetIPChecked(x)         SetFlag(x, FLAG_IPCHECK)
+#define SetInvisible(x)         SetFlag(x, FLAG_INVISIBLE)
+#define SetJunction(x)          SetFlag(x, FLAG_JUNCTION)
+#define SetLocOp(x)             SetFlag(x, FLAG_LOCOP)
+#define SetOper(x)              SetFlag(x, FLAG_OPER)
+#define SetUPing(x)             SetFlag(x, FLAG_UPING)
+#define SetWallops(x)           SetFlag(x, FLAG_WALLOP)
+#define SetServNotice(x)        SetFlag(x, FLAG_SERVNOTICE)
+#define SetHub(x)               SetFlag(x, FLAG_HUB)
+#define SetService(x)           SetFlag(x, FLAG_SERVICE)
+#define SetAccount(x)           SetFlag(x, FLAG_ACCOUNT)
+#define SetHiddenHost(x)        SetFlag(x, FLAG_HIDDENHOST)
+#define SetPingSent(x)          SetFlag(x, FLAG_PINGSENT)
+
+#define ClearAccess(x)          ClrFlag(x, FLAG_CHKACCESS)
+#define ClearBurst(x)           ClrFlag(x, FLAG_BURST)
+#define ClearBurstAck(x)        ClrFlag(x, FLAG_BURST_ACK)
+#define ClearChannelService(x)  ClrFlag(x, FLAG_CHSERV)
+#define ClearDeaf(x)            ClrFlag(x, FLAG_DEAF)
+#define ClearDebug(x)           ClrFlag(x, FLAG_DEBUG)
+#define ClearIPChecked(x)       ClrFlag(x, FLAG_IPCHECK)
+#define ClearInvisible(x)       ClrFlag(x, FLAG_INVISIBLE)
+#define ClearLocOp(x)           ClrFlag(x, FLAG_LOCOP)
+#define ClearOper(x)            ClrFlag(x, FLAG_OPER)
+#define ClearUPing(x)           ClrFlag(x, FLAG_UPING)
+#define ClearWallops(x)         ClrFlag(x, FLAG_WALLOP)
+#define ClearServNotice(x)      ClrFlag(x, FLAG_SERVNOTICE)
+#define ClearHiddenHost(x)      ClrFlag(x, FLAG_HIDDENHOST)
+#define ClearPingSent(x)        ClrFlag(x, FLAG_PINGSENT)
 
 /* free flags */
 #define FREEFLAG_SOCKET        0x0001  /* socket needs to be freed */
@@ -477,13 +496,14 @@ struct Client {
 #define SNO_THROTTLE    0x1000  /* host throttle add/remove notices */
 #define SNO_OLDREALOP   0x2000  /* old oper-only messages */
 #define SNO_CONNEXIT    0x4000  /* client connect/exit (ugh) */
-#define SNO_DEBUG       0x8000  /* debugging messages (DEBUGMODE only) */
+#define SNO_AUTO        0x8000  /* AUTO G-Lines */
+#define SNO_DEBUG       0x10000 /* debugging messages (DEBUGMODE only) */
 
 #ifdef DEBUGMODE
-# define SNO_ALL        0xffff  /* Don't make it larger then significant,
-                                 * that looks nicer */
+# define SNO_ALL        0x1ffff  /* Don't make it larger then significant,
+                                  * that looks nicer */
 #else
-# define SNO_ALL        0x7fff
+# define SNO_ALL        0xffff
 #endif
 
 #define SNO_USER        (SNO_ALL & ~SNO_OPER)
@@ -493,12 +513,9 @@ struct Client {
 #define SNO_OPER (SNO_CONNEXIT|SNO_OLDREALOP)
 #define SNO_NOISY (SNO_SERVKILL|SNO_UNAUTH)
 
-#define PrivSet(pset, priv)    ((pset)->priv_mask[_PRIV_IDX(priv)] |= \
-                                _PRIV_BIT(priv))
-#define PrivClr(pset, priv)    ((pset)->priv_mask[_PRIV_IDX(priv)] &= \
-                                ~(_PRIV_BIT(priv)))
-#define PrivHas(pset, priv)    ((pset)->priv_mask[_PRIV_IDX(priv)] & \
-                                _PRIV_BIT(priv))
+#define PrivSet(fset, flag) FLAGSET_SET(*fset, flag)
+#define PrivClr(fset, flag) FLAGSET_CLEAR(*fset, flag)
+#define PrivHas(fset, flag) FLAGSET_ISSET(*fset, flag)
 
 #define GrantPriv(cli, priv)   (PrivSet(&(cli_privs(cli)), priv))
 #define RevokePriv(cli, priv)  (PrivClr(&(cli_privs(cli)), priv))
index ec10009c3a82f1476081b52cdbc56b199deec311..3be3bd91444d1fbe738904bd29f5afd63bfb8f1c 100644 (file)
@@ -30,6 +30,7 @@
 #include <netinet/in.h>
 
 struct Client;
+struct StatDesc;
 
 #define GLINE_MAX_EXPIRE 604800        /* max expire: 7 days */
 
@@ -90,6 +91,8 @@ extern void gline_free(struct Gline *gline);
 extern void gline_burst(struct Client *cptr);
 extern int gline_resend(struct Client *cptr, struct Gline *gline);
 extern int gline_list(struct Client *sptr, char *userhost);
-extern void gline_stats(struct Client *sptr);
+extern void gline_stats(struct Client *sptr, struct StatDesc *sd, int stat,
+                        char *param);
+extern int gline_memory_count(size_t *gl_size);
 
 #endif /* INCLUDED_gline_h */
index e65ab88ab456a4c00786cea57065472ccb6b994f..55abeaa2a3e71ee364f0078d40539f73a384d707 100644 (file)
@@ -85,6 +85,7 @@ struct Client;
 
 
 extern int m_admin(struct Client*, struct Client*, int, char*[]);
+extern int ms_asll(struct Client*, struct Client*, int, char*[]);
 extern int m_away(struct Client*, struct Client*, int, char*[]);
 extern int m_cnotice(struct Client*, struct Client*, int, char*[]);
 extern int m_cprivmsg(struct Client*, struct Client*, int, char*[]);
@@ -102,6 +103,7 @@ extern int m_links_redirect(struct Client*, struct Client*, int, char*[]);
 extern int m_list(struct Client*, struct Client*, int, char*[]);
 extern int m_lusers(struct Client*, struct Client*, int, char*[]);
 extern int m_map(struct Client*, struct Client*, int, char*[]);
+extern int m_map_redirect(struct Client*, struct Client*, int, char*[]);
 extern int m_mode(struct Client*, struct Client*, int, char*[]);
 extern int m_motd(struct Client*, struct Client*, int, char*[]);
 extern int m_names(struct Client*, struct Client*, int, char*[]);
@@ -131,10 +133,12 @@ extern int m_userhost(struct Client*, struct Client*, int, char*[]);
 extern int m_userip(struct Client*, struct Client*, int, char*[]);
 extern int m_version(struct Client*, struct Client*, int, char*[]);
 extern int m_wallchops(struct Client*, struct Client*, int, char*[]);
+extern int m_wallvoices(struct Client*, struct Client*, int, char*[]);
 extern int m_who(struct Client*, struct Client*, int, char*[]);
 extern int m_whois(struct Client*, struct Client*, int, char*[]);
 extern int m_whowas(struct Client*, struct Client*, int, char*[]);
 extern int mo_admin(struct Client*, struct Client*, int, char*[]);
+extern int mo_asll(struct Client*, struct Client*, int, char*[]);
 extern int mo_clearmode(struct Client*, struct Client*, int, char*[]);
 extern int mo_close(struct Client*, struct Client*, int, char*[]);
 extern int mo_connect(struct Client*, struct Client*, int, char*[]);
@@ -144,7 +148,6 @@ extern int mo_gline(struct Client*, struct Client*, int, char*[]);
 extern int mo_info(struct Client*, struct Client*, int, char*[]);
 extern int mo_jupe(struct Client*, struct Client*, int, char*[]);
 extern int mo_kill(struct Client*, struct Client*, int, char*[]);
-extern int mo_map(struct Client*, struct Client*, int, char*[]);
 extern int mo_notice(struct Client*, struct Client*, int, char*[]);
 extern int mo_oper(struct Client*, struct Client*, int, char*[]);
 extern int mo_opmode(struct Client*, struct Client*, int, char*[]);
@@ -187,6 +190,7 @@ extern int ms_join(struct Client*, struct Client*, int, char*[]);
 extern int ms_jupe(struct Client*, struct Client*, int, char*[]);
 extern int ms_kick(struct Client*, struct Client*, int, char*[]);
 extern int ms_kill(struct Client*, struct Client*, int, char*[]);
+extern int ms_links(struct Client*, struct Client*, int, char*[]);
 extern int ms_lusers(struct Client*, struct Client*, int, char*[]);
 extern int ms_mode(struct Client*, struct Client*, int, char*[]);
 extern int ms_motd(struct Client*, struct Client*, int, char*[]);
@@ -214,6 +218,7 @@ extern int ms_version(struct Client*, struct Client*, int, char*[]);
 extern int ms_wallchops(struct Client*, struct Client*, int, char*[]);
 extern int ms_wallops(struct Client*, struct Client*, int, char*[]);
 extern int ms_wallusers(struct Client*, struct Client*, int, char*[]);
+extern int ms_wallvoices(struct Client*, struct Client*, int, char*[]);
 extern int ms_whois(struct Client*, struct Client*, int, char*[]);
 
 #endif /* INCLUDED_handlers_h */
index 73c289009f5c5b52f0702d3bb30922a0e7a73e78..bca996f6c4cf0ce6751a26156d0356cf64389ef3 100644 (file)
@@ -45,6 +45,7 @@ struct Daemon
  * Proto types
  */
 extern void server_die(const char* message);
+extern void server_panic(const char* message);
 extern void server_restart(const char* message);
 
 extern struct Client  me;
index b2745122d16e89710540c34ebdb76650c33d8b4a..eea764b1c0194c658f5dc4c4d18d7741c7b662bd 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 struct Client;
+struct StatDesc;
 
 enum Feature {
   /* Misc. features */
@@ -34,6 +35,7 @@ enum Feature {
   FEAT_SERVER_PORT,
   FEAT_NODEFAULTMOTD,
   FEAT_MOTD_BANNER,
+  FEAT_PROVIDER,
   FEAT_KILL_IPMISMATCH,
   FEAT_IDLE_FROM_MSG,
   FEAT_HUB,
@@ -45,6 +47,8 @@ enum Feature {
   FEAT_HOST_HIDING,
   FEAT_HIDDEN_HOST,
   FEAT_HIDDEN_IP,
+  FEAT_AUTOHIDE,
+  FEAT_CONNEXIT_NOTICES,
 
   /* features that probably should not be touched */
   FEAT_KILLCHASETIMELIMIT,
@@ -97,6 +101,8 @@ enum Feature {
   FEAT_OPER_LJUPE,
   FEAT_OPER_OPMODE,
   FEAT_OPER_LOPMODE,
+  FEAT_OPER_FORCE_OPMODE,
+  FEAT_OPER_FORCE_LOPMODE,
   FEAT_OPER_BADCHAN,
   FEAT_OPER_LBADCHAN,
   FEAT_OPER_SET,
@@ -112,12 +118,64 @@ enum Feature {
   FEAT_LOCOP_LGLINE,
   FEAT_LOCOP_LJUPE,
   FEAT_LOCOP_LOPMODE,
+  FEAT_LOCOP_FORCE_LOPMODE,
   FEAT_LOCOP_LBADCHAN,
   FEAT_LOCOP_SET,
   FEAT_LOCOP_SEE_IN_SECRET_CHANNELS,
   FEAT_LOCOP_WIDE_GLINE,
   FEAT_LOCOP_LIST_CHAN,
 
+  /* HEAD_IN_SAND Features */
+  FEAT_HIS_SNOTICES,
+  FEAT_HIS_SNOTICES_OPER_ONLY,
+  FEAT_HIS_DESYNCS,
+  FEAT_HIS_DEBUG_OPER_ONLY,
+  FEAT_HIS_WALLOPS,
+  FEAT_HIS_MAP,
+  FEAT_HIS_LINKS,
+  FEAT_HIS_TRACE,
+  FEAT_HIS_STATS_l,
+  FEAT_HIS_STATS_c,
+  FEAT_HIS_STATS_g,
+  FEAT_HIS_STATS_h,
+  FEAT_HIS_STATS_k,
+  FEAT_HIS_STATS_f,
+  FEAT_HIS_STATS_i,
+  FEAT_HIS_STATS_j,
+  FEAT_HIS_STATS_M,
+  FEAT_HIS_STATS_m,
+  FEAT_HIS_STATS_o,
+  FEAT_HIS_STATS_p,
+  FEAT_HIS_STATS_q,
+  FEAT_HIS_STATS_r,
+  FEAT_HIS_STATS_d,
+  FEAT_HIS_STATS_e,
+  FEAT_HIS_STATS_t,
+  FEAT_HIS_STATS_T,
+  FEAT_HIS_STATS_u,
+  FEAT_HIS_STATS_U,
+  FEAT_HIS_STATS_v,
+  FEAT_HIS_STATS_w,
+  FEAT_HIS_STATS_x,
+  FEAT_HIS_STATS_y,
+  FEAT_HIS_STATS_z,
+  FEAT_HIS_WHOIS_SERVERNAME,
+  FEAT_HIS_WHOIS_IDLETIME,
+  FEAT_HIS_WHO_SERVERNAME,
+  FEAT_HIS_WHO_HOPCOUNT,
+  FEAT_HIS_BANWHO,
+  FEAT_HIS_KILLWHO,
+  FEAT_HIS_REWRITE,
+  FEAT_HIS_REMOTE,
+  FEAT_HIS_NETSPLIT,
+  FEAT_HIS_SERVERNAME,
+  FEAT_HIS_SERVERINFO,
+  FEAT_HIS_URLSERVERS,
+
+  /* Misc. random stuff */
+  FEAT_NETWORK,
+  FEAT_URL_CLIENTS,
+
   FEAT_LAST_F
 };
 
@@ -133,7 +191,8 @@ extern int feature_get(struct Client* from, const char* const* fields,
 extern void feature_unmark(void);
 extern void feature_mark(void);
 
-extern void feature_report(struct Client* to);
+extern void feature_report(struct Client* to, struct StatDesc* sd, int stat,
+                           char* param);
 
 extern int feature_int(enum Feature feat);
 extern int feature_bool(enum Feature feat);
index 26d5e86e34c123f375656e8bd71aa1b1a414ddfb..ec03e1699b16a4b900c3c0fe21bcad51710f8929 100644 (file)
@@ -36,6 +36,7 @@
 #endif
 
 struct Client;
+struct StatDesc;
 
 struct Listener {
   struct Listener* next;               /* list node pointer */
@@ -62,8 +63,8 @@ extern void        close_listeners(void);
 extern void        count_listener_memory(int* count_out, size_t* size_out);
 extern const char* get_listener_name(const struct Listener* listener);
 extern void        mark_listeners_closing(void);
-extern void        show_ports(struct Client* client, int show_hidden,
-                              int port, int count);
+extern void show_ports(struct Client* client, struct StatDesc* sd, int stat,
+                       char* param);
 extern void        release_listener(struct Listener* listener);
 
 #endif /* INCLUDED_listener_h */
index 5ee6e050e149336c1606a5c08a70896802d4bfa4..130ce162bbd63d71699fdbd1d5c001de08ac2f03 100644 (file)
@@ -34,6 +34,7 @@
 
 struct Client;
 struct TRecord;
+struct StatDesc;
 
 struct Motd {
   struct Motd*         next;
@@ -85,6 +86,8 @@ void motd_add(const char *hostmask, const char *path);
 void motd_clear(void);
 
 /* This is called to report T-lines */
-void motd_report(struct Client *to);
+void motd_report(struct Client *to, struct StatDesc *sd, int stat,
+                 char *param);
+void motd_memory_count(struct Client *cptr);
 
 #endif /* INCLUDED_motd_h */
index 878ebb9831d367735e96e5ca020151de2a9975ec..9087926bd2a567c1044519779e6161ad7b542a64 100644 (file)
@@ -198,6 +198,10 @@ struct Client;
 #define TOK_WALLCHOPS           "WC"
 #define CMD_WALLCHOPS          MSG_WALLCHOPS, TOK_WALLCHOPS
 
+#define MSG_WALLVOICES           "WALLVOICES"     /* WV */
+#define TOK_WALLVOICES           "WV"
+#define CMD_WALLVOICES         MSG_WALLVOICES, TOK_WALLVOICES
+
 #define MSG_CPRIVMSG            "CPRIVMSG"      /* CPRI */
 #define TOK_CPRIVMSG            "CP"
 #define CMD_CPRIVMSG           MSG_CPRIVMSG, TOK_CPRIVMSG
@@ -330,6 +334,10 @@ struct Client;
 #define TOK_ACCOUNT            "AC"
 #define CMD_ACCOUNT            MSG_ACCOUNT, TOK_ACCOUNT
 
+#define MSG_ASLL               "ASLL"          /* ASLL */
+#define TOK_ASLL               "LL"
+#define CMD_ASLL               MSG_ASLL, TOK_ASLL
+
 #define MSG_POST                "POST"          /* POST */
 #define TOK_POST                "POST"
 
index ae92211096980258e262e8ccef2d3a4c60fdc604..b7b5535dd5e93ab05d8a193fc75e590500f33bcd 100644 (file)
@@ -35,6 +35,7 @@
 struct iovec;
 
 struct Client;
+struct StatDesc;
 
 struct MsgCounts {
   int alloc;
@@ -92,8 +93,10 @@ extern void msgq_append(struct Client *dest, struct MsgBuf *mb,
                        const char *format, ...);
 extern void msgq_clean(struct MsgBuf *mb);
 extern void msgq_add(struct MsgQ *mq, struct MsgBuf *mb, int prio);
-extern void msgq_count_memory(size_t *msg_alloc, size_t *msg_used,
-                             size_t *msgbuf_alloc, size_t *msgbuf_used);
+extern void msgq_count_memory(struct Client *cptr,
+                              size_t *msg_alloc, size_t *msg_used);
+extern void msgq_histogram(struct Client *cptr, struct StatDesc *sd, int stat,
+                           char *param);
 extern unsigned int msgq_bufleft(struct MsgBuf *mb);
 
 #endif /* INCLUDED_msgq_h */
index ebbb45fab57a1507c728dd2fa8f1867dc9aed2c5..ec3807972d009437166c3996e925326f07b87601 100644 (file)
@@ -112,7 +112,7 @@ extern const struct Numeric* get_error_numeric(int err);
        RPL_STATSNLINE       226           unreal
        RPL_STATSGLINE       227           Dalnet 
        RPL_STATSVLINE       227           unreal */
-
+#define RPL_STATSQLINE       228        /* Undernet extension */
 #define RPL_SERVICEINFO      231       /* unused */
 #define RPL_ENDOFSERVICES    232       /* unused */
 /*     RPL_RULES            232        unreal */
@@ -250,7 +250,7 @@ extern const struct Numeric* get_error_numeric(int err);
 /*     RPL_LISTSYNTAX       334           unreal */
 /*      RPL_CHANPASSOK       338           IRCnet extension (?)*/
 #define        RPL_WHOISACTUALLY    338        /* Undernet extension, dalnet */
-/*     RPL_BADCHANPASS      339           mIRC/DALnet extension */
+/*     RPL_BADCHANPASS      339           IRCnet extension (?) */
 #define RPL_USERIP           340        /* Undernet extension */
 #define RPL_INVITING         341
 /*      RPL_SUMMONING        342           removed from RFC1459 */
@@ -441,11 +441,13 @@ extern const struct Numeric* get_error_numeric(int err);
 #define ERR_TOOMANYUSERS     519       /* Undernet extension -Kev */
 /*     ERR_OPERONLY         520        unreal */
 #define ERR_MASKTOOWIDE             520        /* Undernet extension -Kev */
-/*     ERR_WHOTRUNC         520        austnet
+/*      ERR_WHOTRUNC         520        austnet */
+/*      ERR_LISTSYNTAX       521        dalnet
        ERR_LISTSYNTAX       521        dalnet
        ERR_WHOSYNTAX        522        dalnet
        ERR_WHOLIMEXCEED     523        dalnet */
-
+#define ERR_QUARANTINED      524       /* Undernet extension -Vampire */
 #define ERR_NOTLOWEROPLEVEL  550       /* Undernet extension */
 #define ERR_NOTMANAGER       551       /* Undernet extension */
 #define ERR_CHANSECURED      552       /* Undernet extension */
index 43a4d5b70d61ae95758239c0bba7dab010a6318a..df6a7e4e565c4ae72d3bc20380d97279edf0597b 100644 (file)
@@ -24,5 +24,6 @@ struct Client;
  */
 
 extern char *militime(char* sec, char* usec);
+extern char *militime_float(char *start);
 
 #endif /* INCLUDED_opercmds_h */
index ac61e36e00d44b8aef7c1f6a8ecd22d4f463fd01..8823ce74c1bff47a527190471a446b98ce1560d6 100644 (file)
@@ -66,6 +66,8 @@ struct ConfItem
   unsigned short port;
   unsigned char bits; /* Number of bits for ipkills. */
   struct Privs privs; /* Priviledges for opers. */
+  /* Used to detect if a privilege has been touched. */
+  struct Privs privs_dirty;
 };
 
 struct ServerConf {
@@ -81,6 +83,13 @@ struct ServerConf {
   struct ConnectionClass*  conn_class;
 };
 
+struct qline
+{
+  struct qline *next;
+  char *chname;
+  char *reason;
+};
+
 struct DenyConf {
   struct DenyConf*    next;
   char*               hostmask;
@@ -161,6 +170,7 @@ extern struct tm        motd_tm;
 extern struct MotdItem* motd;
 extern struct MotdItem* rmotd;
 extern struct TRecord*  tdata;
+extern struct qline*   GlobalQuarantineList;
 
 /*
  * Proto types
@@ -192,8 +202,7 @@ extern void read_tlines(void);
 extern int find_kill(struct Client *cptr);
 extern int find_restrict(struct Client *cptr);
 extern struct MotdItem* read_motd(const char* motdfile);
-
-extern void set_initial_oper_privs(struct ConfItem *oper, int flags);
+extern const char *find_quarantine(const char* chname);
 extern void lookup_confhost(struct ConfItem *aconf);
 
 extern void yyerror(const char *msg);
index 9bc2560f3b1e14e64c35d5d8baffe8255abbdc95..30cf0152135c6297f7b6d113e9080cd8c293bd58 100644 (file)
@@ -14,6 +14,7 @@
 #endif
 
 struct Client;
+struct StatDesc;
 
 #ifdef DEBUGMODE
 
@@ -45,7 +46,8 @@ struct Client;
 
 extern void vdebug(int level, const char *form, va_list vl);
 extern void debug(int level, const char *form, ...);
-extern void send_usage(struct Client *cptr, char *nick);
+extern void send_usage(struct Client *cptr, struct StatDesc *sd, int stat,
+                       char *param);
 
 #else /* !DEBUGMODE */
 
@@ -56,6 +58,7 @@ extern void send_usage(struct Client *cptr, char *nick);
 
 extern const char* debug_serveropts(void);
 extern void debug_init(int use_tty);
-extern void count_memory(struct Client *cptr, char *nick);
+extern void count_memory(struct Client *cptr, struct StatDesc *sd, int stat,
+                         char *param);
 
 #endif /* INCLUDED_s_debug_h */
index 1dc068b60401841dd406bb647b9b3072be610ef9..8c2983b8ed6c8f354ef7fd85819a03a9ef396f3f 100644 (file)
@@ -16,6 +16,7 @@
 
 
 struct Client;
+struct StatDesc;
 struct ConfItem;
 
 /*-----------------------------------------------------------------------------
@@ -74,7 +75,8 @@ extern const char* get_client_host(const struct Client *cptr);
 extern void get_sockhost(struct Client *cptr, char *host);
 extern int vexit_client_msg(struct Client *cptr, struct Client *bcptr,
     struct Client *sptr, const char *pattern, va_list vl);
-extern void tstats(struct Client *cptr, char *name);
+extern void tstats(struct Client *cptr, struct StatDesc *sd, int stat,
+                   char *param);
 
 extern struct ServerStatistics* ServerStats;
 
index 17cc5eeb691fda79489b57871edcbc012628aac1..967aeac441dc7ecf9c4e6ad902519608b703fc61 100644 (file)
 
 struct Client;
 
-extern const char *statsinfo[];
+struct StatDesc;
+
+/* Source of /stats, stats descriptor, stats char, extra param (might be 0) */
+typedef void (*StatFunc)(struct Client *, struct StatDesc *, int, char *);
+
+struct StatDesc
+{
+  char         sd_c;           /* stats character */
+  unsigned int sd_flags;       /* flags to control the stats */
+  enum Feature sd_control;     /* feature controlling stats */
+  StatFunc     sd_func;        /* function to dispatch to */
+  int          sd_funcdata;    /* extra data for the function */
+  char        *sd_desc;        /* descriptive text */
+};
+
+#define STAT_FLAG_OPERONLY 0x01    /* Oper-only stat */
+#define STAT_FLAG_OPERFEAT 0x02    /* Oper-only if the feature is true */
+#define STAT_FLAG_CASESENS 0x04    /* Flag is case-sensitive */
+#define STAT_FLAG_VARPARAM 0x08    /* may have an extra parameter */
+
+extern struct StatDesc statsinfo[];
+extern struct StatDesc *statsmap[];
+
 extern void report_stats(struct Client *sptr, char stat);
 extern void report_configured_links(struct Client *sptr, int mask);
 extern int hunt_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[], char stat, int MustBeOper);
 
-extern void report_crule_list(struct Client* to, int mask);
-extern void report_motd_list(struct Client* to);
-extern void report_deny_list(struct Client* to);
+extern void stats_init(void);
 
 #endif /* INCLUDED_s_stats_h */
index 5615abb5cd63c81a3c7e103847de6b75dd11d6e1..587b599d5e1933be89daea882dcd84e237835f02 100644 (file)
@@ -14,6 +14,7 @@ struct Client;
 struct User;
 struct Channel;
 struct MsgBuf;
+struct Flags;
 
 /*
  * Macros
@@ -40,6 +41,11 @@ struct MsgBuf;
 #define HUNTED_ISME     0       /* if this server should execute the command */
 #define HUNTED_PASS     1       /* if message passed onwards successfully */
 
+/* send sets for send_umode() */
+#define ALL_UMODES 0  /* both local and global user modes */
+#define SEND_UMODES 1  /* global user modes only */
+#define SEND_UMODES_BUT_OPER 2  /* global user modes except for FLAG_OPER */
+
 /* used when sending to #mask or $mask */
 
 #define MATCH_SERVER  1
@@ -61,11 +67,10 @@ extern int          register_user(struct Client* cptr, struct Client* sptr,
 
 extern void         user_count_memory(size_t* count_out, size_t* bytes_out);
 
-extern int do_nick_name(char* nick);
 extern int set_nick_name(struct Client* cptr, struct Client* sptr,
                          const char* nick, int parc, char* parv[]);
-extern void send_umode_out(struct Client* cptr, struct Client* sptr, int old,
-                          int prop);
+extern void send_umode_out(struct Client* cptr, struct Client* sptr,
+                          struct Flags* old, int prop);
 extern int whisper(struct Client* source, const char* nick,
                    const char* channel, const char* text, int is_notice);
 extern void send_user_info(struct Client* to, char* names, int rpl,
@@ -88,7 +93,8 @@ extern int hunt_server_prio_cmd(struct Client *from, const char *cmd,
                                int server, int parc, char *parv[]);
 extern struct Client* next_client(struct Client* next, const char* ch);
 extern char *umode_str(struct Client *cptr);
-extern void send_umode(struct Client *cptr, struct Client *sptr, int old, int sendmask);
+extern void send_umode(struct Client *cptr, struct Client *sptr,
+                       struct Flags *old, int sendset);
 extern int del_silence(struct Client *sptr, char *mask);
 extern void set_snomask(struct Client *, unsigned int, int);
 extern int is_snomask(char *);
index 5554050fa3bc3dbc3612ff456287cd99cfe8de81..bf7e754936a9d8fb349f04050c1772e9652748fc 100644 (file)
@@ -24,6 +24,7 @@ struct MsgBuf;
  */
 extern void send_buffer(struct Client* to, struct MsgBuf* buf, int prio);
 
+extern void kill_highest_sendq(int servers_too);
 extern void flush_connections(struct Client* cptr);
 extern void send_queued(struct Client *to);
 
@@ -71,6 +72,8 @@ extern void sendcmdto_channel_butone(struct Client *from, const char *cmd,
 #define SKIP_DEAF      0x01    /* skip users that are +d */
 #define SKIP_BURST     0x02    /* skip users that are bursting */
 #define SKIP_NONOPS    0x04    /* skip users that aren't chanops */
+#define SKIP_NONVOICES  0x08    /* skip users that aren't voiced (includes
+                                   chanops) */
 
 /* Send command to all users having a particular flag set */
 extern void sendwallto_group_butone(struct Client *from, int type, 
index 2975fecbc19b2109c608f5255526518c98e3ca2a..b173c3024aa123ebd8fa8045d94b53422d72011d 100644 (file)
@@ -52,6 +52,10 @@ struct Server {
   unsigned short  nn_last;      /* Last numeric nick for p9 servers only */
   unsigned int    nn_mask;      /* [Remote] FD_SETSIZE - 1 */
   char          nn_capacity[4]; /* numeric representation of server capacity */
+  
+  int            asll_rtt;     /* AsLL round-trip time */
+  int            asll_to;      /* AsLL upstream lag */
+  int            asll_from;    /* AsLL downstream lag */
 
   char *last_error_msg;         /* Allocated memory with last message receive with an ERROR */
   char by[NICKLEN + 1];
index 329aff89c781995cbe265da056baafaefa6625d1..23eee8520de16e23fa10bd3e8c3ea94cad812da5 100644 (file)
@@ -34,6 +34,7 @@
 #define FEATURES1 \
                 "WHOX"\
                 " WALLCHOPS"\
+                " WALLVOICES"\
                 " USERIP"\
                 " CPRIVMSG"\
                 " CNOTICE"\
@@ -57,7 +58,8 @@
                        feature_int(FEAT_MAXBANS), NICKLEN, TOPICLEN, \
                        AWAYLEN, TOPICLEN
 
-#define FEATURESVALUES2 "+#&", "(ov)@+", "b,k,l,imnpstr", "rfc1459", NETWORK
+#define FEATURESVALUES2 "#&", "(ov)@+", "b,k,l,imnpstr", "rfc1459", \
+                        feature_str(FEAT_NETWORK)
 
 #endif /* INCLUDED_supported_h */
 
index c6dfd18cf9a942ca3b1b59e732550fc6e29c10de..d44c16aee19014068a1370f564f314a92d8c8150 100644 (file)
@@ -26,6 +26,7 @@
 #define INCLUDED_userload_h
 
 struct Client;
+struct StatDesc;
 
 /*
  * Structures
@@ -42,7 +43,8 @@ struct current_load_st {
  */
 
 extern void update_load(void);
-extern void calc_load(struct Client *sptr);
+extern void calc_load(struct Client *sptr, struct StatDesc *sd, int stat,
+                      char *param);
 extern void initload(void);
 
 extern struct current_load_st current_load;
index 298dae02b047b5a9c2e1e7ff29c58a85f4fc8e5d..c91d40251cc8d5ca460a6602328878a203018f78 100644 (file)
@@ -36,14 +36,20 @@ struct Channel;
 #define WHO_FIELD_DIS 256
 #define WHO_FIELD_REN 512
 #define WHO_FIELD_IDL 1024
+#define WHO_FIELD_ACC 2048
 
 #define WHO_FIELD_DEF ( WHO_FIELD_NIC | WHO_FIELD_UID | WHO_FIELD_HOS | WHO_FIELD_SER )
 
 #define IS_VISIBLE_USER(s,ac) ((s==ac) || (!IsInvisible(ac)))
 
-#define SEE_LUSER(s, ac, b) (IS_VISIBLE_USER(s, ac) || ((b & WHOSELECT_EXTRA) && MyConnect(ac) && HasPriv((s), PRIV_SHOW_INVIS | PRIV_SHOW_ALL_INVIS)))
+#define SEE_LUSER(s, ac, b) (IS_VISIBLE_USER(s, ac) || \
+                             ((b & WHOSELECT_EXTRA) && MyConnect(ac) && \
+                             (HasPriv((s), PRIV_SHOW_INVIS) || \
+                              HasPriv((s), PRIV_SHOW_ALL_INVIS))))
 
-#define SEE_USER(s, ac, b) (SEE_LUSER(s, ac, b) || ((b & WHOSELECT_EXTRA) && HasPriv((s), PRIV_SHOW_ALL_INVIS)))
+#define SEE_USER(s, ac, b) (SEE_LUSER(s, ac, b) || \
+                            ((b & WHOSELECT_EXTRA) && \
+                              HasPriv((s), PRIV_SHOW_ALL_INVIS)))
 
 #define SHOW_MORE(sptr, counter) (HasPriv(sptr, PRIV_UNLIMIT_QUERY) || (!(counter-- < 0)) )
 
index 47c102f9eeb74faa7edaaf8079f436c1a66155cd..04ffb3acf501fd962afc4a3e37fa5cf42a32ff97 100644 (file)
@@ -384,7 +384,7 @@ void ip_registry_disconnect(struct Client *cptr)
   if (0 == entry) {
     /*
      * trying to find an entry for a server causes this to happen,
-     * servers should never have FLAGS_IPCHECK set
+     * servers should never have FLAG_IPCHECK set
      */
     return;
   }
index 0b55039afa3b34cc05e77f294aeb388b6e902613..2aeed4a358b62d94907ad7d101b73f162fe0b8b7 100644 (file)
@@ -111,6 +111,7 @@ IRCD_SRC = \
        listener.c \
        m_account.c \
        m_admin.c \
+       m_asll.c \
        m_away.c \
        m_burst.c \
        m_clearmode.c \
@@ -175,6 +176,7 @@ IRCD_SRC = \
        m_wallchops.c \
        m_wallops.c \
        m_wallusers.c \
+       m_wallvoices.c \
        m_who.c \
        m_whois.c \
        m_whowas.c \
index 56fa07fe81ff1177df5966167e188fe37902d733..62f21cfda22a1dcccbcfa4bdf3b2e3b368725da7 100644 (file)
@@ -31,7 +31,6 @@
 #include "ircd_defs.h"
 #include "ircd_features.h"
 #include "ircd_log.h"
-#include "ircd_policy.h"
 #include "ircd_reply.h"
 #include "ircd_snprintf.h"
 #include "ircd_string.h"
@@ -383,11 +382,9 @@ int add_banid(struct Client *cptr, struct Channel *chptr, char *banid,
     assert(0 != ban->value.ban.banstr);
     strcpy(ban->value.ban.banstr, banid);
 
-#ifdef HEAD_IN_SAND_BANWHO
-    if (IsServer(cptr))
+    if (IsServer(cptr) && feature_bool(FEAT_HIS_BANWHO))
       DupString(ban->value.ban.who, cli_name(&me));
     else
-#endif
       DupString(ban->value.ban.who, cli_name(cptr));
     assert(0 != ban->value.ban.who);
 
@@ -442,6 +439,7 @@ static int is_banned(struct Client *cptr, struct Channel *chptr,
                      struct Membership* member)
 {
   struct SLink* tmp;
+  char          tmphost[HOSTLEN + 1];
   char          nu_host[NUH_BUFSIZE];
   char          nu_realhost[NUH_BUFSIZE];
   char          nu_ip[NUI_BUFSIZE];
@@ -457,10 +455,23 @@ static int is_banned(struct Client *cptr, struct Channel *chptr,
 
   s = make_nick_user_host(nu_host, cli_name(cptr), (cli_user(cptr))->username,
                          (cli_user(cptr))->host);
-  if (HasHiddenHost(cptr))
-    sr = make_nick_user_host(nu_realhost, cli_name(cptr),
-                            (cli_user(cptr))->username,
-                            cli_user(cptr)->realhost);
+  if (IsAccount(cptr))
+  {
+    if (HasHiddenHost(cptr))
+    {
+      sr = make_nick_user_host(nu_realhost, cli_name(cptr),
+                               (cli_user(cptr))->username,
+                               cli_user(cptr)->realhost);
+    }
+    else
+    {
+      ircd_snprintf(0, tmphost, HOSTLEN, "%s.%s",
+                    cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST));
+      sr = make_nick_user_host(nu_realhost, cli_name(cptr),
+                               cli_user(cptr)->username,
+                               tmphost);      
+    }
+  }
 
   for (tmp = chptr->banlist; tmp; tmp = tmp->next) {
     if ((tmp->flags & CHFL_BAN_IPMASK)) {
@@ -682,12 +693,11 @@ int client_can_send_to_channel(struct Client *cptr, struct Channel *chptr)
   member = find_channel_member(cptr, chptr);
 
   /*
-   * You can't speak if your off channel, if the channel is modeless, or
-   * +n (no external messages) or +m (moderated).
+   * You can't speak if you're off channel, and it is +n (no external messages)
+   * or +m (moderated).
    */
   if (!member) {
     if ((chptr->mode.mode & (MODE_NOPRIVMSGS|MODE_MODERATED)) ||
-       IsModelessChannel(chptr->chname) ||
        ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(cptr)))
       return 0;
     else
@@ -1156,7 +1166,8 @@ int can_join(struct Client *sptr, struct Channel *chptr, char *key)
      a HACK(4) notice will be sent if he would not have been supposed
      to join normally. */ 
   if (IsLocalChannel(chptr->chname) && HasPriv(sptr, PRIV_WALK_LCHAN) &&
-      !BadPtr(key) && compall("OVERRIDE",key) == 0)
+      !BadPtr(key) && compall("OVERRIDE",chptr->mode.key) != 0 &&
+      compall("OVERRIDE",key) == 0)
     overrideJoin = MAGIC_OPER_OVERRIDE;
 
   if (chptr->mode.mode & MODE_INVITEONLY)
@@ -1523,8 +1534,9 @@ modebuf_flush_int(struct ModeBuf *mbuf, int all)
   if (mbuf->mb_add == 0 && mbuf->mb_rem == 0 && mbuf->mb_count == 0)
     return 0;
 
-  /* Ok, if we were given the OPMODE flag, hide the source if its a user */
-  if (mbuf->mb_dest & MODEBUF_DEST_OPMODE && !IsServer(mbuf->mb_source))
+  /* Ok, if we were given the OPMODE flag, or its a server, hide the source.
+   */
+  if (mbuf->mb_dest & MODEBUF_DEST_OPMODE || IsServer(mbuf->mb_source))
     app_source = &me;
   else
     app_source = mbuf->mb_source;
@@ -1666,11 +1678,8 @@ modebuf_flush_int(struct ModeBuf *mbuf, int all)
     if (mbuf->mb_dest & MODEBUF_DEST_HACK2)
       sendto_opmask_butone(0, SNO_HACK2, "HACK(2): %s MODE %s %s%s%s%s%s%s "
                           "[%Tu]",
-#ifdef HEAD_IN_SAND_SNOTICES
-                          cli_name(mbuf->mb_source),
-#else
-                          cli_name(app_source),
-#endif
+                           cli_name(feature_bool(FEAT_HIS_SNOTICES) ?
+                                    mbuf->mb_source : app_source),
                           mbuf->mb_channel->chname,
                           rembuf_i ? "-" : "", rembuf, addbuf_i ? "+" : "",
                           addbuf, remstr, addstr,
@@ -1679,11 +1688,8 @@ modebuf_flush_int(struct ModeBuf *mbuf, int all)
     if (mbuf->mb_dest & MODEBUF_DEST_HACK3)
       sendto_opmask_butone(0, SNO_HACK3, "BOUNCE or HACK(3): %s MODE %s "
                           "%s%s%s%s%s%s [%Tu]",
-#ifdef HEAD_IN_SAND_SNOTICES
-                          cli_name(mbuf->mb_source),
-#else
-                          cli_name(app_source),
-#endif
+                           cli_name(feature_bool(FEAT_HIS_SNOTICES) ? 
+                                    mbuf->mb_source : app_source),
                           mbuf->mb_channel->chname, rembuf_i ? "-" : "",
                           rembuf, addbuf_i ? "+" : "", addbuf, remstr, addstr,
                           mbuf->mb_channel->creationtime);
@@ -2190,7 +2196,7 @@ mode_parse_key(struct ParseState *state, int *flag_p)
     return;
   state->done |= DONE_KEY;
 
-  t_len = KEYLEN + 1;
+  t_len = KEYLEN;
 
   /* clean up the key string */
   s = t_str;
@@ -2570,8 +2576,9 @@ mode_parse_ban(struct ParseState *state, int *flag_p)
       } else if (!mmatch(t_str, ban->value.ban.banstr))
        ban->flags |= MODE_DEL; /* mark ban for deletion: overlapping */
 
-      if (!ban->next && (newban->flags & MODE_ADD)) {
-       ban->next = newban; /* add our"ban with its flags */
+      if (!ban->next && (newban->flags & MODE_ADD))
+      {
+       ban->next = newban; /* add our ban with its flags */
        break; /* get out of loop */
       }
     }
@@ -2646,7 +2653,7 @@ mode_process_bans(struct ParseState *state)
       } else {
        if (state->flags & MODE_PARSE_SET && MyUser(state->sptr) &&
            (len > (feature_int(FEAT_AVBANLEN) * feature_int(FEAT_MAXBANS)) ||
-            count >= feature_int(FEAT_MAXBANS))) {
+            count > feature_int(FEAT_MAXBANS))) {
          send_reply(state->sptr, ERR_BANLISTFULL, state->chptr->chname,
                     ban->value.ban.banstr);
          count--;
@@ -2778,7 +2785,8 @@ mode_process_clients(struct ParseState *state)
       if (MyUser(state->sptr)) {
 
        /* don't allow local opers to be deopped on local channels */
-       if (state->cli_change[i].client != state->sptr &&
+       if (MyUser(state->sptr) &&
+            state->cli_change[i].client != state->sptr &&
            IsLocalChannel(state->chptr->chname) &&
            HasPriv(state->cli_change[i].client, PRIV_DEOP_LCHAN)) {
          send_reply(state->sptr, ERR_ISOPERLCHAN,
@@ -3106,6 +3114,7 @@ void
 joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, unsigned int flags)
 {
   unsigned int len;
+  int is_local;
 
   assert(0 != jbuf);
 
@@ -3116,6 +3125,8 @@ joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, unsigned int flags)
     return;
   }
 
+  is_local = IsLocalChannel(chan->chname);
+
   if (jbuf->jb_type == JOINBUF_TYPE_PART ||
       jbuf->jb_type == JOINBUF_TYPE_PARTALL) {
     /* Send notification to channel */
@@ -3135,14 +3146,14 @@ joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, unsigned int flags)
      * the original m_part.c */
 
     if (jbuf->jb_type == JOINBUF_TYPE_PARTALL ||
-       IsLocalChannel(chan->chname)) /* got to remove user here */
+       is_local) /* got to remove user here */
       remove_user_from_channel(jbuf->jb_source, chan);
   } else {
     /* Add user to channel */
     add_user_to_channel(chan, jbuf->jb_source, flags, 0);
 
     /* send notification to all servers */
-    if (jbuf->jb_type != JOINBUF_TYPE_CREATE && !IsLocalChannel(chan->chname))
+    if (jbuf->jb_type != JOINBUF_TYPE_CREATE && !is_local)
       sendcmdto_serv_butone(jbuf->jb_source, CMD_JOIN, jbuf->jb_connect,
                            "%H %Tu", chan, chan->creationtime);
 
@@ -3150,14 +3161,13 @@ joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, unsigned int flags)
     sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, chan, NULL, ":%H", chan);
 
     /* send an op, too, if needed */
-    if (!MyUser(jbuf->jb_source) && jbuf->jb_type == JOINBUF_TYPE_CREATE &&
-       !IsModelessChannel(chan->chname))
+    if (!MyUser(jbuf->jb_source) && jbuf->jb_type == JOINBUF_TYPE_CREATE)
       sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_MODE, chan, NULL, "%H +o %C",
                                chan, jbuf->jb_source);
   }
 
   if (jbuf->jb_type == JOINBUF_TYPE_PARTALL ||
-      jbuf->jb_type == JOINBUF_TYPE_JOIN || IsLocalChannel(chan->chname))
+      jbuf->jb_type == JOINBUF_TYPE_JOIN || is_local)
     return; /* don't send to remote */
 
   /* figure out if channel name will cause buffer to be overflowed */
@@ -3220,3 +3230,14 @@ joinbuf_flush(struct JoinBuf *jbuf)
 
   return 0;
 }
+
+/* Returns TRUE (1) if client is invited, FALSE (0) if not */
+int IsInvited(struct Client* cptr, struct Channel* chptr)
+{
+  struct SLink *lp;
+
+  for (lp = (cli_user(cptr))->invited; lp; lp = lp->next)
+    if (lp->value.chptr == chptr)
+      return 1;
+  return 0;
+}
index ba5d7191d29eebe78874eb6ca74955df8bfce70d..c922dbb686655dddae50100e8282b1cacd93e5c7 100644 (file)
@@ -231,7 +231,8 @@ struct ConnectionClass* find_class(const char *name)
 }
 
 void
-report_classes(struct Client *sptr)
+report_classes(struct Client *sptr, struct StatDesc *sd, int stat,
+               char *param)
 {
   struct ConnectionClass *cltmp;
 
index fc4dd9c7ee0bbdc836ce95d04144e8cb402ed8f0..f960a1d99f470e29e5e817e71b494c1d035a218a 100644 (file)
@@ -103,74 +103,72 @@ void client_add_sendq(struct Connection* con, struct Connection** con_p)
 
 static struct
 {
-  unsigned int priv;
+  enum Priv priv;
+  enum
+    {
+      FEATFLAG_DISABLES_PRIV,
+      FEATFLAG_ENABLES_PRIV,
+      FEATFLAG_GLOBAL_OPERS,
+      FEATFLAG_LOCAL_OPERS,
+      FEATFLAG_ALL_OPERS
+    } flag;
   enum Feature feat;
-  unsigned int flag;
 } feattab[] =
   {
-    { PRIV_WHOX, FEAT_LAST_F, (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_DISPLAY, FEAT_LAST_F, (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_CHAN_LIMIT, FEAT_OPER_NO_CHAN_LIMIT, (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_MODE_LCHAN, FEAT_OPER_MODE_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_LOCAL_OPMODE, FEAT_OPER_MODE_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_WALK_LCHAN, FEAT_OPER_WALK_THROUGH_LMODES,
-      (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_DEOP_LCHAN, FEAT_NO_OPER_DEOP_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_SHOW_INVIS, FEAT_SHOW_INVISIBLE_USERS, (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_SHOW_ALL_INVIS, FEAT_SHOW_ALL_INVISIBLE_USERS,
-      (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_UNLIMIT_QUERY, FEAT_UNLIMIT_OPER_QUERY,
-      (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_LIST_CHAN, FEAT_LIST_CHAN, (FLAGS_OPER | FLAGS_LOCOP) },
-    { PRIV_KILL, FEAT_LOCAL_KILL_ONLY, 0 },
-    { PRIV_GLINE, FEAT_CONFIG_OPERCMDS, ~0 },
-    { PRIV_JUPE, FEAT_CONFIG_OPERCMDS, ~0 },
-    { PRIV_OPMODE, FEAT_CONFIG_OPERCMDS, ~0 },
-    { PRIV_BADCHAN, FEAT_CONFIG_OPERCMDS, ~0 },
-    { PRIV_PROPAGATE, FEAT_LAST_F, FLAGS_OPER },
-    { PRIV_SEE_OPERS, FEAT_LAST_F, FLAGS_OPER },
-    { PRIV_KILL, FEAT_OPER_KILL, FLAGS_OPER },
-    { PRIV_LOCAL_KILL, FEAT_OPER_KILL, FLAGS_OPER },
-    { PRIV_REHASH, FEAT_OPER_REHASH, FLAGS_OPER },
-    { PRIV_RESTART, FEAT_OPER_RESTART, FLAGS_OPER },
-    { PRIV_DIE, FEAT_OPER_DIE, FLAGS_OPER },
-    { PRIV_GLINE, FEAT_OPER_GLINE, FLAGS_OPER },
-    { PRIV_LOCAL_GLINE, FEAT_OPER_LGLINE, FLAGS_OPER },
-    { PRIV_JUPE, FEAT_OPER_JUPE, FLAGS_OPER },
-    { PRIV_LOCAL_JUPE, FEAT_OPER_LJUPE, FLAGS_OPER },
-    { PRIV_OPMODE, FEAT_OPER_OPMODE, FLAGS_OPER },
-    { PRIV_LOCAL_OPMODE, FEAT_OPER_LOPMODE, FLAGS_OPER },
-    { PRIV_BADCHAN, FEAT_OPER_BADCHAN, FLAGS_OPER },
-    { PRIV_LOCAL_BADCHAN, FEAT_OPER_LBADCHAN, FLAGS_OPER },
-    { PRIV_SET, FEAT_OPER_SET, FLAGS_OPER },
-    { PRIV_SEE_CHAN, FEAT_OPERS_SEE_IN_SECRET_CHANNELS, FLAGS_OPER },
-    { PRIV_WIDE_GLINE, FEAT_OPER_WIDE_GLINE, FLAGS_OPER },
-    { PRIV_LIST_CHAN, FEAT_OPER_LIST_CHAN, FLAGS_OPER },
-    { PRIV_LOCAL_KILL, FEAT_LOCOP_KILL, FLAGS_LOCOP },
-    { PRIV_REHASH, FEAT_LOCOP_REHASH, FLAGS_LOCOP },
-    { PRIV_RESTART, FEAT_LOCOP_RESTART, FLAGS_LOCOP },
-    { PRIV_DIE, FEAT_LOCOP_DIE, FLAGS_LOCOP },
-    { PRIV_LOCAL_GLINE, FEAT_LOCOP_LGLINE, FLAGS_LOCOP },
-    { PRIV_LOCAL_JUPE, FEAT_LOCOP_LJUPE, FLAGS_LOCOP },
-    { PRIV_LOCAL_OPMODE, FEAT_LOCOP_LOPMODE, FLAGS_LOCOP },
-    { PRIV_LOCAL_BADCHAN, FEAT_LOCOP_LBADCHAN, FLAGS_LOCOP },
-    { PRIV_SET, FEAT_LOCOP_SET, FLAGS_LOCOP },
-    { PRIV_SEE_CHAN, FEAT_LOCOP_SEE_IN_SECRET_CHANNELS, FLAGS_LOCOP },
-    { PRIV_WIDE_GLINE, FEAT_LOCOP_WIDE_GLINE, FLAGS_LOCOP },
-    { PRIV_LIST_CHAN, FEAT_LOCOP_LIST_CHAN, FLAGS_LOCOP },
-    { 0, FEAT_LAST_F, 0 }
+    { PRIV_WHOX, FEAT_LAST_F, FEATFLAG_ALL_OPERS },
+    { PRIV_DISPLAY, FEAT_LAST_F, FEATFLAG_ALL_OPERS },
+    { PRIV_CHAN_LIMIT, FEAT_OPER_NO_CHAN_LIMIT, FEATFLAG_ALL_OPERS },
+    { PRIV_MODE_LCHAN, FEAT_OPER_MODE_LCHAN, FEATFLAG_ALL_OPERS },
+    { PRIV_LOCAL_OPMODE, FEAT_OPER_MODE_LCHAN, FEATFLAG_ALL_OPERS },
+    { PRIV_WALK_LCHAN, FEAT_OPER_WALK_THROUGH_LMODES, FEATFLAG_ALL_OPERS },
+    { PRIV_DEOP_LCHAN, FEAT_NO_OPER_DEOP_LCHAN, FEATFLAG_ALL_OPERS },
+    { PRIV_SHOW_INVIS, FEAT_SHOW_INVISIBLE_USERS, FEATFLAG_ALL_OPERS },
+    { PRIV_SHOW_ALL_INVIS, FEAT_SHOW_ALL_INVISIBLE_USERS, FEATFLAG_ALL_OPERS },
+    { PRIV_UNLIMIT_QUERY, FEAT_UNLIMIT_OPER_QUERY, FEATFLAG_ALL_OPERS },
+    
+    { PRIV_KILL, FEAT_LOCAL_KILL_ONLY, FEATFLAG_DISABLES_PRIV },
+    { PRIV_GLINE, FEAT_CONFIG_OPERCMDS, FEATFLAG_ENABLES_PRIV },
+    { PRIV_JUPE, FEAT_CONFIG_OPERCMDS, FEATFLAG_ENABLES_PRIV },
+    { PRIV_OPMODE, FEAT_CONFIG_OPERCMDS, FEATFLAG_ENABLES_PRIV },
+    { PRIV_BADCHAN, FEAT_CONFIG_OPERCMDS, FEATFLAG_ENABLES_PRIV },
+    
+    { PRIV_PROPAGATE, FEAT_LAST_F, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_SEE_OPERS, FEAT_LAST_F, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_KILL, FEAT_OPER_KILL, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_LOCAL_KILL, FEAT_OPER_KILL, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_REHASH, FEAT_OPER_REHASH, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_RESTART, FEAT_OPER_RESTART, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_DIE, FEAT_OPER_DIE, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_GLINE, FEAT_OPER_GLINE, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_LOCAL_GLINE, FEAT_OPER_LGLINE, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_JUPE, FEAT_OPER_JUPE, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_LOCAL_JUPE, FEAT_OPER_LJUPE, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_OPMODE, FEAT_OPER_OPMODE, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_LOCAL_OPMODE, FEAT_OPER_LOPMODE, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_FORCE_OPMODE, FEAT_OPER_FORCE_OPMODE, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_FORCE_LOCAL_OPMODE, FEAT_OPER_FORCE_LOPMODE, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_BADCHAN, FEAT_OPER_BADCHAN, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_LOCAL_BADCHAN, FEAT_OPER_LBADCHAN, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_SET, FEAT_OPER_SET, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_SEE_CHAN, FEAT_OPERS_SEE_IN_SECRET_CHANNELS, FEATFLAG_GLOBAL_OPERS },
+    { PRIV_WIDE_GLINE, FEAT_OPER_WIDE_GLINE, FEATFLAG_GLOBAL_OPERS },
+    
+    { PRIV_LOCAL_KILL, FEAT_LOCOP_KILL, FEATFLAG_LOCAL_OPERS },
+    { PRIV_REHASH, FEAT_LOCOP_REHASH, FEATFLAG_LOCAL_OPERS },
+    { PRIV_RESTART, FEAT_LOCOP_RESTART, FEATFLAG_LOCAL_OPERS },
+    { PRIV_DIE, FEAT_LOCOP_DIE, FEATFLAG_LOCAL_OPERS },
+    { PRIV_LOCAL_GLINE, FEAT_LOCOP_LGLINE, FEATFLAG_LOCAL_OPERS },
+    { PRIV_LOCAL_JUPE, FEAT_LOCOP_LJUPE, FEATFLAG_LOCAL_OPERS },
+    { PRIV_LOCAL_OPMODE, FEAT_LOCOP_LOPMODE, FEATFLAG_LOCAL_OPERS },
+    { PRIV_FORCE_LOCAL_OPMODE, FEAT_LOCOP_FORCE_LOPMODE, FEATFLAG_LOCAL_OPERS },
+    { PRIV_LOCAL_BADCHAN, FEAT_LOCOP_LBADCHAN, FEATFLAG_LOCAL_OPERS },
+    { PRIV_SET, FEAT_LOCOP_SET, FEATFLAG_LOCAL_OPERS },
+    { PRIV_SEE_CHAN, FEAT_LOCOP_SEE_IN_SECRET_CHANNELS, FEATFLAG_LOCAL_OPERS },
+    { PRIV_WIDE_GLINE, FEAT_LOCOP_WIDE_GLINE, FEATFLAG_LOCAL_OPERS },
+    
+    { PRIV_LAST_PRIV, FEAT_LAST_F, 0 }
   };
 
-void
-set_initial_oper_privs(struct ConfItem *oper, int flags)
-{
-  int i;
-  memset(&oper->privs, 0, sizeof(oper->privs));
-  for (i = 0; feattab[i].priv; i++)
-    if ((feattab[i].flag | flags) != 0 && feattab[i].flag != ~0)
-      PrivSet(&oper->privs, feattab[i].priv);
-}
-
 /* client_set_privs(struct Client* client)
  *
  * Sets the privileges for opers.
@@ -196,12 +194,39 @@ client_set_privs(struct Client *client, struct ConfItem *oper)
   /* Copy across privs from the config. */
   cli_privs(client) = oper->privs;
 
-  /* Remove privileges disallowed by features... */
-  for (i = 0; feattab[i].priv; i++)
-    if (feattab[i].flag == 0 && feature_bool(feattab[i].feat))      
-      PrivClr(&cli_privs(client), feattab[i].priv);
-    else if (feattab[i].flag == ~0 && !feature_bool(feattab[i].feat))
+  /* Now go through the features and set the non-dirty flags to their feature
+   * determined defaults...
+   */
+  for (i = 0; feattab[i].priv != PRIV_LAST_PRIV; i++)
+  {
+    if (PrivHas(&oper->privs_dirty, feattab[i].priv))
+      continue;
+    if (feattab[i].feat != FEAT_LAST_F && !feature_bool(feattab[i].priv))
+      continue;
+    switch (feattab[i].flag)
+    {
+    case FEATFLAG_ENABLES_PRIV:
+      if (!feature_bool(feattab[i].feat))
+        continue;
+      PrivSet(&cli_privs(client), feattab[i].priv);
+      continue;
+    case FEATFLAG_DISABLES_PRIV:
       PrivClr(&cli_privs(client), feattab[i].priv);
+      continue;
+    case FEATFLAG_ALL_OPERS:
+      if (IsAnOper(client))
+        PrivSet(&cli_privs(client), feattab[i].priv);
+      continue;
+    case FEATFLAG_GLOBAL_OPERS:
+      if (IsOper(client))
+        PrivSet(&cli_privs(client), feattab[i].priv);
+      continue;
+    case FEATFLAG_LOCAL_OPERS:
+      if (IsLocOp(client))
+        PrivSet(&cli_privs(client), feattab[i].priv);
+      continue;
+    }
+  }
 
   /* This should be handled in the config, but lets be sure... */
   if (PrivHas(&cli_privs(client), PRIV_PROPAGATE))
@@ -229,7 +254,8 @@ static struct {
   P(GLINE),          P(LOCAL_GLINE),    P(JUPE),          P(LOCAL_JUPE),
   P(OPMODE),         P(LOCAL_OPMODE),   P(SET),           P(WHOX),
   P(BADCHAN),        P(LOCAL_BADCHAN),  P(SEE_CHAN),      P(PROPAGATE),
-  P(DISPLAY),        P(SEE_OPERS),      P(WIDE_GLINE),
+  P(DISPLAY),        P(SEE_OPERS),      P(FORCE_OPMODE),  P(FORCE_LOCAL_OPMODE),
+  P(WIDE_GLINE),
 #undef P
   { 0, 0 }
 };
index 8ac50dfacb9b3bafdbf099bf8368404da50f3c80..ebbe6424e91cd930f3d52f66c1442e2f3d05509d 100644 (file)
@@ -27,7 +27,6 @@
 #include "ircd_alloc.h"
 #include "ircd_features.h"
 #include "ircd_log.h"
-#include "ircd_policy.h"
 #include "ircd_reply.h"
 #include "ircd_snprintf.h"
 #include "ircd_string.h"
@@ -36,6 +35,7 @@
 #include "s_bsd.h"
 #include "s_debug.h"
 #include "s_misc.h"
+#include "s_stats.h"
 #include "send.h"
 #include "struct.h"
 #include "support.h"
@@ -317,9 +317,9 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
   assert(0 != reason);
 
   /* NO_OLD_GLINE allows *@#channel to work correctly */
-  if (*userhost == '#' || *userhost == '&' || *userhost == '+'
+  if (*userhost == '#' || *userhost == '&'
 # ifndef NO_OLD_GLINE
-      || userhost[2] == '#' || userhost[2] == '&' || userhost[2] == '+'
+      || userhost[2] == '#' || userhost[2] == '&'
 # endif /* OLD_GLINE */
       ) {
     if ((flags & GLINE_LOCAL) && !HasPriv(sptr, PRIV_LOCAL_BADCHAN))
@@ -327,7 +327,7 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
 
     flags |= GLINE_BADCHAN;
 # ifndef NO_OLD_GLINE
-    if (userhost[2] == '#' || userhost[2] == '&' || userhost[2] == '+')
+    if (userhost[2] == '#' || userhost[2] == '&')
       user = userhost + 2;
     else
 # endif /* OLD_GLINE */
@@ -368,18 +368,16 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
   expire += CurrentTime; /* convert from lifetime to timestamp */
 
   /* Inform ops... */
-  sendto_opmask_butone(0, SNO_GLINE, "%s adding %s %s for %s%s%s, expiring at "
-                      "%Tu: %s",
-#ifdef HEAD_IN_SAND_SNOTICES
-                      cli_name(sptr),
-#else
-                      IsServer(sptr) ? cli_name(sptr) :
-                      cli_name((cli_user(sptr))->server),
-#endif
-                      flags & GLINE_LOCAL ? "local" : "global",
-                      flags & GLINE_BADCHAN ? "BADCHAN" : "GLINE", user,
-                      flags & GLINE_BADCHAN ? "" : "@",
-                      flags & GLINE_BADCHAN ? "" : host,
+  sendto_opmask_butone(0, ircd_strncmp(reason, "AUTO", 4) ? SNO_GLINE :
+                       SNO_AUTO, "%s adding %s %s for %s%s%s, expiring at "
+                       "%Tu: %s",
+                       (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
+                         cli_name(sptr) :
+                         cli_name((cli_user(sptr))->server),
+                      (flags & GLINE_LOCAL) ? "local" : "global",
+                      (flags & GLINE_BADCHAN) ? "BADCHAN" : "GLINE", user,
+                      (flags & GLINE_BADCHAN) ? "" : "@",
+                      (flags & GLINE_BADCHAN) ? "" : host,
                       expire + TSoffset, reason);
 
   /* and log it */
@@ -431,18 +429,15 @@ gline_activate(struct Client *cptr, struct Client *sptr, struct Gline *gline,
 
   /* Inform ops and log it */
   sendto_opmask_butone(0, SNO_GLINE, "%s activating global %s for %s%s%s, "
-                      "expiring at %Tu: %s",
-#ifdef HEAD_IN_SAND_SNOTICES
-                      cli_name(sptr),
-#else
-                      IsServer(sptr) ? cli_name(sptr) :
-                      cli_name((cli_user(sptr))->server),
-#endif
-                      GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
-                      gline->gl_user, GlineIsBadChan(gline) ? "" : "@",
-                      GlineIsBadChan(gline) ? "" : gline->gl_host,
-                      gline->gl_expire + TSoffset, gline->gl_reason);
-
+                       "expiring at %Tu: %s",
+                       (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
+                         cli_name(sptr) :
+                         cli_name((cli_user(sptr))->server),
+                       GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
+                       gline->gl_user, GlineIsBadChan(gline) ? "" : "@",
+                       GlineIsBadChan(gline) ? "" : gline->gl_host,
+                       gline->gl_expire + TSoffset, gline->gl_reason);
+  
   log_write(LS_GLINE, L_INFO, LOG_NOSNOTICE,
            "%#C activating global %s for %s%s%s, expiring at %Tu: %s", sptr,
            GlineIsBadChan(gline) ? "BADCHAN" : "GLINE", gline->gl_user,
@@ -495,12 +490,9 @@ gline_deactivate(struct Client *cptr, struct Client *sptr, struct Gline *gline,
   /* Inform ops and log it */
   sendto_opmask_butone(0, SNO_GLINE, "%s %s %s for %s%s%s, expiring at %Tu: "
                       "%s",
-#ifdef HEAD_IN_SAND_SNOTICES
-                      cli_name(sptr),
-#else
-                      IsServer(sptr) ? cli_name(sptr) :
-                      cli_name((cli_user(sptr))->server),
-#endif
+                       (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
+                         cli_name(sptr) :
+                         cli_name((cli_user(sptr))->server),
                       msg, GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
                       gline->gl_user, GlineIsBadChan(gline) ? "" : "@",
                       GlineIsBadChan(gline) ? "" : gline->gl_host,
@@ -546,9 +538,9 @@ gline_find(char *userhost, unsigned int flags)
   }
 
   if ((flags & (GLINE_BADCHAN | GLINE_ANY)) == GLINE_BADCHAN ||
-      *userhost == '#' || *userhost == '&' || *userhost == '+'
+      *userhost == '#' || *userhost == '&'
 #ifndef NO_OLD_GLINE
-      || userhost[2] == '#' || userhost[2] == '&' || userhost[2] == '+'
+      || userhost[2] == '#' || userhost[2] == '&'
 #endif /* NO_OLD_GLINE */
       )
     return 0;
@@ -734,7 +726,8 @@ gline_list(struct Client *sptr, char *userhost)
 }
 
 void
-gline_stats(struct Client *sptr)
+gline_stats(struct Client *sptr, struct StatDesc *sd, int stat,
+            char *param)
 {
   struct Gline *gline;
   struct Gline *sgline;
@@ -749,3 +742,21 @@ gline_stats(struct Client *sptr)
                 gline->gl_expire + TSoffset, gline->gl_reason);
   }
 }
+
+int
+gline_memory_count(size_t *gl_size)
+{
+  struct Gline *gline;
+  unsigned int gl = 0;
+  
+  for (gline = GlobalGlineList; gline; gline = gline->gl_next)
+  {
+    gl++;
+    gl_size += sizeof(struct Gline);
+    gl_size += gline->gl_user ? (strlen(gline->gl_user) + 1) : 0;
+    gl_size += gline->gl_host ? (strlen(gline->gl_host) + 1) : 0;
+    gl_size += gline->gl_reason ? (strlen(gline->gl_reason) + 1) : 0;
+  }
+  return gl;
+}
+
index 87c171f7049d81ed1b3b2b6c9ffed392db316459..27d56ba3d48d62fbab8c46a21f3804b32b5d5e8b 100644 (file)
@@ -42,6 +42,7 @@
 #include "msg.h"
 #include "numeric.h"
 #include "numnicks.h"
+#include "opercmds.h"
 #include "parse.h"
 #include "res.h"
 #include "s_auth.h"
@@ -115,7 +116,8 @@ int running = 1;
 /*----------------------------------------------------------------------------
  * API: server_die
  *--------------------------------------------------------------------------*/
-void server_die(const char* message) {
+void server_die(const char *message)
+{
   /* log_write will send out message to both log file and as server notice */
   log_write(LS_SYSTEM, L_CRIT, 0, "Server terminating: %s", message);
   flush_connections(0);
@@ -123,11 +125,24 @@ void server_die(const char* message) {
   running = 0;
 }
 
+/*----------------------------------------------------------------------------
+ * API: server_panic
+ *--------------------------------------------------------------------------*/
+void server_panic(const char *message)
+{
+  /* inhibit sending server notice--we may be panicing due to low memory */
+  log_write(LS_SYSTEM, L_CRIT, LOG_NOSNOTICE, "Server panic: %s", message);
+  flush_connections(0);
+  log_close();
+  close_connections(1);
+  exit(1);
+}
 
 /*----------------------------------------------------------------------------
  * API: server_restart
  *--------------------------------------------------------------------------*/
-void server_restart(const char* message) {
+void server_restart(const char *message)
+{
   static int restarting = 0;
 
   /* inhibit sending any server notices; we may be in a loop */
@@ -345,7 +360,7 @@ static void check_pings(struct Event* ev) {
    
     Debug((DEBUG_DEBUG, "check_pings(%s)=status:%s limit: %d current: %d",
           cli_name(cptr),
-          (cli_flags(cptr) & FLAGS_PINGSENT) ? "[Ping Sent]" : "[]", 
+          IsPingSent(cptr) ? "[Ping Sent]" : "[]", 
           max_ping, (int)(CurrentTime - cli_lasttime(cptr))));
           
 
@@ -359,50 +374,58 @@ static void check_pings(struct Event* ev) {
       continue;
     }
 
+    /* Quit the client after max_ping*2 - they should have answered by now */
+    if (CurrentTime-cli_lasttime(cptr) >= (max_ping*2) )
+    {
+      /* If it was a server, then tell ops about it. */
+      if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr))
+        sendto_opmask_butone(0, SNO_OLDSNO,
+                             "No response from %s, closing link",
+                             cli_name(cptr));
+      exit_client_msg(cptr, cptr, &me, "Ping timeout");
+      continue;
+    }
+
     /* Unregistered clients pingout after max_ping seconds, they don't
      * get given a second chance - if they were then people could not quite
      * finish registration and hold resources without being subject to k/g
      * lines
      */
-    if (!IsRegistered(cptr)) {
+    if (!IsRegistered(cptr))
+    {
       /* Display message if they have sent a NICK and a USER but no
        * nospoof PONG.
        */
-      if (*(cli_name(cptr)) && cli_user(cptr) && *(cli_user(cptr))->username) {
+      if (*(cli_name(cptr)) && cli_user(cptr) && *(cli_user(cptr))->username)
+      {
        send_reply(cptr, SND_EXPLICIT | ERR_BADPING,
                   ":Your client may not be compatible with this server.");
        send_reply(cptr, SND_EXPLICIT | ERR_BADPING,
-                  ":Compatible clients are available at "
-                  URL_CLIENTS);
+                   ":Compatible clients are available at %s",
+                   feature_str(FEAT_URL_CLIENTS));
       }    
       exit_client_msg(cptr,cptr,&me, "Ping Timeout");
       continue;
     }
     
-    if (!(cli_flags(cptr) & FLAGS_PINGSENT)) {
+    if (!IsPingSent(cptr))
+    {
       /* If we havent PINGed the connection and we havent heard from it in a
        * while, PING it to make sure it is still alive.
        */
-      cli_flags(cptr) |= FLAGS_PINGSENT;
+      SetPingSent(cptr);
 
       /* If we're late in noticing don't hold it against them :) */
       cli_lasttime(cptr) = CurrentTime - max_ping;
       
       if (IsUser(cptr))
-       sendrawto_one(cptr, MSG_PING " :%s", cli_name(&me));
+        sendrawto_one(cptr, MSG_PING " :%s", cli_name(&me));
       else
-       sendcmdto_one(&me, CMD_PING, cptr, ":%s", cli_name(&me));
-    }
-    
-    /* Quit the client after max_ping*2 - they should have answered by now */
-    if (CurrentTime-cli_lasttime(cptr) >= (max_ping*2) ) {
-      /* If it was a server, then tell ops about it. */
-      if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr))
-       sendto_opmask_butone(0, SNO_OLDSNO,
-                            "No response from %s, closing link",
-                            cli_name(cptr));
-      exit_client_msg(cptr, cptr, &me, "Ping timeout");
-      continue;
+      {
+        char *asll_ts = militime_float(NULL);
+        sendcmdto_one(&me, CMD_PING, cptr, "!%s %s %s", asll_ts,
+                      cli_name(cptr), asll_ts);
+      }
     }
     
     expire = cli_lasttime(cptr) + max_ping * 2;
index 2c4b9667ebd41e1d9f49833eeea5189e379c18cd..f0ad61081167a0d8707bb18198cbd14d87919fd2 100644 (file)
@@ -241,6 +241,7 @@ static struct FeatureDesc {
   F_I(SERVER_PORT, FEAT_OPER, 4400, 0),
   F_B(NODEFAULTMOTD, 0, 1, 0),
   F_S(MOTD_BANNER, FEAT_NULL, 0, 0),
+  F_S(PROVIDER, FEAT_NULL, 0, 0),
   F_B(KILL_IPMISMATCH, FEAT_OPER, 0, 0),
   F_B(IDLE_FROM_MSG, 0, 1, 0),
   F_B(HUB, 0, 0, 0),
@@ -249,15 +250,17 @@ static struct FeatureDesc {
   F_N(RANDOM_SEED, FEAT_NODISP, random_seed_set, 0, 0, 0, 0, 0, 0),
   F_S(DEFAULT_LIST_PARAM, FEAT_NULL, 0, list_set_default),
   F_I(NICKNAMEHISTORYLENGTH, 0, 800, whowas_realloc),
-  F_B(HOST_HIDING, 0, 0, 0),
+  F_B(HOST_HIDING, 0, 1, 0),
   F_S(HIDDEN_HOST, FEAT_CASE, "users.undernet.org", 0),
   F_S(HIDDEN_IP, 0, "127.0.0.1", 0),
+  F_B(AUTOHIDE, 0, 1, 0),
+  F_B(CONNEXIT_NOTICES, 0, 0, 0),
 
   /* features that probably should not be touched */
   F_I(KILLCHASETIMELIMIT, 0, 30, 0),
   F_I(MAXCHANNELSPERUSER, 0, 10, 0),
   F_I(AVBANLEN, 0, 40, 0),
-  F_I(MAXBANS, 0, 30, 0),
+  F_I(MAXBANS, 0, 45, 0),
   F_I(MAXSILES, 0, 15, 0),
   F_I(HANGONGOODLINK, 0, 300, 0),
   F_I(HANGONRETRYDELAY, 0, 10, 0),
@@ -304,6 +307,8 @@ static struct FeatureDesc {
   F_B(OPER_LJUPE, 0, 1, 0),
   F_B(OPER_OPMODE, 0, 1, 0),
   F_B(OPER_LOPMODE, 0, 1, 0),
+  F_B(OPER_FORCE_OPMODE, 0, 1, 0),
+  F_B(OPER_FORCE_LOPMODE, 0, 1, 0),
   F_B(OPER_BADCHAN, 0, 0, 0),
   F_B(OPER_LBADCHAN, 0, 0, 0),
   F_B(OPER_SET, 0, 0, 0),
@@ -319,12 +324,63 @@ static struct FeatureDesc {
   F_B(LOCOP_LGLINE, 0, 1, 0),
   F_B(LOCOP_LJUPE, 0, 1, 0),
   F_B(LOCOP_LOPMODE, 0, 1, 0),
+  F_B(LOCOP_FORCE_LOPMODE, 0, 1, 0),
   F_B(LOCOP_LBADCHAN, 0, 0, 0),
   F_B(LOCOP_SET, 0, 0, 0),
   F_B(LOCOP_SEE_IN_SECRET_CHANNELS, 0, 0, 0),
   F_B(LOCOP_WIDE_GLINE, 0, 0, 0),
   F_B(LOCOP_LIST_CHAN, 0, 0, 0),
 
+  /* HEAD_IN_SAND Features */
+  F_B(HIS_SNOTICES, 0, 1, 0),
+  F_B(HIS_SNOTICES_OPER_ONLY, 0, 1, 0),
+  F_B(HIS_DESYNCS, 0, 1, 0),
+  F_B(HIS_DEBUG_OPER_ONLY, 0, 1, 0),
+  F_B(HIS_WALLOPS, 0, 1, 0),
+  F_B(HIS_MAP, 0, 1, 0),
+  F_B(HIS_LINKS, 0, 1, 0),
+  F_B(HIS_TRACE, 0, 1, 0),
+  F_B(HIS_STATS_l, 0, 1, 0),
+  F_B(HIS_STATS_c, 0, 1, 0),
+  F_B(HIS_STATS_g, 0, 1, 0),
+  F_B(HIS_STATS_h, 0, 1, 0),
+  F_B(HIS_STATS_k, 0, 1, 0),
+  F_B(HIS_STATS_f, 0, 1, 0),
+  F_B(HIS_STATS_i, 0, 1, 0),
+  F_B(HIS_STATS_j, 0, 1, 0),
+  F_B(HIS_STATS_M, 0, 1, 0),
+  F_B(HIS_STATS_m, 0, 1, 0),
+  F_B(HIS_STATS_o, 0, 1, 0),
+  F_B(HIS_STATS_p, 0, 1, 0),
+  F_B(HIS_STATS_q, 0, 1, 0),
+  F_B(HIS_STATS_r, 0, 1, 0),
+  F_B(HIS_STATS_d, 0, 1, 0),
+  F_B(HIS_STATS_e, 0, 1, 0),
+  F_B(HIS_STATS_t, 0, 1, 0),
+  F_B(HIS_STATS_T, 0, 1, 0),
+  F_B(HIS_STATS_u, 0, 0, 0),
+  F_B(HIS_STATS_U, 0, 1, 0),
+  F_B(HIS_STATS_v, 0, 1, 0),
+  F_B(HIS_STATS_w, 0, 0, 0),
+  F_B(HIS_STATS_x, 0, 1, 0),
+  F_B(HIS_STATS_y, 0, 1, 0),
+  F_B(HIS_STATS_z, 0, 1, 0),
+  F_B(HIS_WHOIS_SERVERNAME, 0, 1, 0),
+  F_B(HIS_WHOIS_IDLETIME, 0, 1, 0),
+  F_B(HIS_WHO_SERVERNAME, 0, 1, 0),
+  F_B(HIS_WHO_HOPCOUNT, 0, 1, 0),
+  F_B(HIS_BANWHO, 0, 1, 0),
+  F_B(HIS_KILLWHO, 0, 1, 0),
+  F_B(HIS_REWRITE, 0, 1, 0),
+  F_I(HIS_REMOTE, 0, 1, 0),
+  F_B(HIS_NETSPLIT, 0, 1, 0),
+  F_S(HIS_SERVERNAME, 0, "*.undernet.org", 0),
+  F_S(HIS_SERVERINFO, 0, "The Undernet Underworld", 0),
+  F_S(HIS_URLSERVERS, 0, "http://www.undernet.org/servers.php", 0),
+
+  /* Misc. random stuff */
+  F_S(NETWORK, 0, "UnderNet", 0),
+  F_S(URL_CLIENTS, 0, "ftp://ftp.undernet.org/pub/irc/clients", 0),
 #undef F_S
 #undef F_B
 #undef F_I
@@ -687,7 +743,7 @@ feature_init(void)
 
 /* report all F-lines */
 void
-feature_report(struct Client* to)
+feature_report(struct Client* to, struct StatDesc* sd, int stat, char* param)
 {
   int i;
 
index f3d893b34e83f35cab0b67a611b1a2ae8fcf1d80..35ecc04194dd57d1df3910688a11483c0aa79152 100644 (file)
@@ -120,7 +120,9 @@ all return ALL;
 ip return IP;
 crule return CRULE;
 kill return KILL;
+quarantine return QUARANTINE;
 features return FEATURES;
+channel return CHANNEL;
 bypass_local_channel_limits return TPRIV_CHAN_LIMIT;
 set_local_channel_modes return TPRIV_MODE_LCHAN;
 protected_local_channel return TPRIV_DEOP_LCHAN;
index bbc3e363640c837883984211bb8e1009fbc7827f..37e942bc8e77eb6b76203153393f7c540cdb5faa 100644 (file)
@@ -637,7 +637,8 @@ log_set_file(const char *subsys, const char *filename)
     desc->mark &= ~LOG_MARK_FILE; /* file has been reset to defaults */
 
   /* no change, don't go to the trouble of destroying and recreating */
-  if (desc->file && filename && !strcmp(desc->file->file, filename))
+  if (desc->file && desc->file->file && filename &&
+      !strcmp(desc->file->file, filename))
     return 0;
 
   /* debug log is special, since it has to be opened on fd 2 */
@@ -868,10 +869,12 @@ log_feature_report(struct Client *to, int flag)
 {
   int i;
 
-  for (i = 0; i < LS_LAST_SYSTEM; i++) {
+  for (i = 0; i < LS_LAST_SYSTEM; i++)
+  {
     if (logDesc[i].mark & LOG_MARK_FILE) /* report file */
       send_reply(to, SND_EXPLICIT | RPL_STATSFLINE, "F LOG %s FILE %s",
-                logDesc[i].name, logDesc[i].file->file);
+                 logDesc[i].name, (logDesc[i].file && logDesc[i].file->file ?
+                                   logDesc[i].file->file : "(terminal)"));
 
     if (logDesc[i].mark & LOG_MARK_FACILITY) /* report facility */
       send_reply(to, SND_EXPLICIT | RPL_STATSFLINE, "F LOG %s FACILITY %s",
index 8db80e66e084f8d839ce2ddaea9e43dda145bad1..4e63ff98f3f3c06e6dc6a8a24c77daaa6f76f38b 100644 (file)
@@ -62,6 +62,8 @@
   extern struct DenyConf*   denyConfList;
   extern struct CRuleConf*  cruleConfList;
   extern struct ServerConf* serverConfList;
+  extern struct qline     *GlobalQuarantineList;
 
   int yylex(void);
   /* Now all the globals we need :/... */
@@ -73,6 +75,7 @@
   struct ConfItem *aconf;
   struct DenyConf *dconf;
   struct ServerConf *sconf;
+  struct qline *qconf = NULL;
 %}
 
 %token <text> QSTRING
@@ -85,6 +88,7 @@
 %token CONTACT
 %token CONNECT
 %token CLASS
+%token CHANNEL
 %token PINGFREQ
 %token CONNECTFREQ
 %token MAXLINKS
 %token ALL
 %token IP
 %token FEATURES
+%token QUARANTINE
 /* and now a lot of priviledges... */
 %token TPRIV_CHAN_LIMIT, TPRIV_MODE_LCHAN, TPRIV_DEOP_LCHAN, TPRIV_WALK_LCHAN
 %token TPRIV_KILL, TPRIV_LOCAL_KILL, TPRIV_REHASH, TPRIV_RESTART, TPRIV_DIE
 blocks: blocks block | block;
 block: adminblock | generalblock | classblock | connectblock |
        serverblock | operblock | portblock | jupeblock | clientblock |
-       killblock | cruleblock | motdblock | featuresblock;
+       killblock | cruleblock | motdblock | featuresblock | quarantineblock;
 
 /* The timespec, sizespec and expr was ripped straight from
  * ircd-hybrid-7. */
@@ -470,7 +475,6 @@ operblock: OPER
   aconf = MyMalloc(sizeof(*aconf));
   memset(aconf, 0, sizeof(*aconf));
   aconf->status = CONF_OPERATOR;
-  set_initial_oper_privs(aconf, (FLAGS_OPER | FLAGS_LOCOP));
 } '{' operitems '}' ';'
 {
   if (aconf->name != NULL && aconf->passwd != NULL && aconf->host != NULL)
@@ -509,12 +513,8 @@ operlocal: LOCAL '=' YES ';'
    * permission values here. But for now, I am just going with local 
    * opers... */
   aconf->status = CONF_LOCOP;
-  /* XXX blow away existing priviledges. */
-  set_initial_oper_privs(aconf, FLAGS_LOCOP);
 } | LOCAL '=' NO ';'
 {
-  /* XXX blow away existing priviledges. */
-  set_initial_oper_privs(aconf, (FLAGS_OPER|FLAGS_LOCOP));
   aconf->status = CONF_OPERATOR;
 };
 
@@ -540,9 +540,15 @@ operclass: CLASS '=' QSTRING ';'
 operpriv: privtype '=' yesorno ';'
 {
   if ($3 == 1)
+  {
+    PrivSet(&aconf->privs_dirty, $1);
     PrivSet(&aconf->privs, $1);
+  }
   else
+  {
+    PrivSet(&aconf->privs_dirty, $1);
     PrivClr(&aconf->privs, $1);
+  }
 };
 
 privtype: TPRIV_CHAN_LIMIT { $$ = PRIV_CHAN_LIMIT; } |
@@ -865,3 +871,36 @@ extrastring: QSTRING
   if (stringno < MAX_STRINGS)
     stringlist[stringno++] = $1;
 };
+
+quarantineblock: QUARANTINE '{'
+{
+  if (qconf != NULL)
+    qconf = MyMalloc(sizeof(*qconf));
+  else
+  {
+    if (qconf->chname != NULL)
+      MyFree(qconf->chname);
+    if (qconf->reason != NULL)
+      MyFree(qconf->reason);
+  }
+  memset(qconf, 0, sizeof(*qconf));
+} quarantineitems '}' ';'
+{
+  if (qconf->chname == NULL || qconf->reason == NULL)
+  {
+    log_write(LS_CONFIG, L_ERROR, 0, "quarantine blocks need a channel name "
+              "and a reason.");
+    return;
+  }
+  qconf->next = GlobalQuarantineList;
+  GlobalQuarantineList = qconf;
+  qconf = NULL;
+};
+
+quarantineitems: CHANNEL NAME '=' QSTRING ';'
+{
+  DupString(qconf->chname, yylval.text);
+} | REASON '=' QSTRING ';'
+{
+  DupString(qconf->reason, yylval.text);
+};
index d49905070a80b79a0e0d65f0fcbb8eb835b96164..2b5992688bfab1c8886711a7b4bf5e95a8fed478 100644 (file)
@@ -31,6 +31,7 @@
 #include "ircd.h"
 #include "ircd_chattr.h"
 #include "ircd_reply.h"
+#include "ircd_features.h"
 #include "ircd_string.h"
 #include "match.h"
 #include "msg.h"
@@ -158,8 +159,7 @@ void relay_directed_message(struct Client* sptr, char* name, char* server, const
   assert(0 != text);
   assert(0 != server);
 
-  if ((acptr = FindServer(server + 1)) == NULL ||
-      !IsChannelService(acptr))
+  if ((acptr = FindServer(server + 1)) == NULL || !IsChannelService(acptr))
   {
     send_reply(sptr, ERR_NOSUCHNICK, name);
     return;
@@ -313,8 +313,9 @@ void server_relay_private_message(struct Client* sptr, const char* name, const c
    * nickname addressed?
    */
   if (0 == (acptr = findNUser(name)) || !IsUser(acptr)) {
-    send_reply(sptr, SND_EXPLICIT | ERR_NOSUCHNICK, "* :Target left " NETWORK ". "
-              "Failed to deliver: [%.20s]", text);
+    send_reply(sptr, SND_EXPLICIT | ERR_NOSUCHNICK, "* :Target left %s. "
+              "Failed to deliver: [%.20s]", feature_str(FEAT_NETWORK),
+               text);
     return;
   }
   if (is_silenced(sptr, acptr))
index 8706e8069311dc8b9a48fa03b7f811677a546e56..0a762aad3a71bea4f67a2ffc7573bbcc5cccd58f 100644 (file)
@@ -1434,7 +1434,9 @@ adds(struct BufData *buf_p, int s_len, const char *s)
 {
   int overflow = 0;
 
-  while (*s && s_len) { /* while the string exists and has non-zero length */
+  /* while the string exists and has non-zero length */
+  while (s_len && *s)
+  {
     /* poor man's inlining; see addc(), above */
     if (buf_p->limit == 0) { /* We've gone past the limit... */
       buf_p->overflow++;
index 80691c7150fdfdffaa9c0b80885e560d650366cd..e76455b2b338b7e3ed4df07a938ef10c81e16524 100644 (file)
@@ -27,8 +27,8 @@
 #include "hash.h"
 #include "ircd.h"
 #include "ircd_alloc.h"
+#include "ircd_features.h"
 #include "ircd_log.h"
-#include "ircd_policy.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "match.h"
@@ -123,13 +123,10 @@ jupe_add(struct Client *cptr, struct Client *sptr, char *server, char *reason,
 
   /* Inform ops and log it */
   sendto_opmask_butone(0, SNO_NETWORK, "%s adding %sJUPE for %s, expiring at "
-                      "%Tu: %s",
-#ifdef HEAD_IN_SAND_SNOTICES
-                      cli_name(sptr),
-#else
-                      IsServer(sptr) ? cli_name(sptr) :
-                      cli_name(cli_user(sptr)->server),
-#endif
+                       "%Tu: %s",
+                       (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
+                         cli_name(sptr) :
+                         cli_name((cli_user(sptr))->server),
                       flags & JUPE_LOCAL ? "local " : "", server,
                       expire + TSoffset, reason);
 
@@ -173,12 +170,9 @@ jupe_activate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
   /* Inform ops and log it */
   sendto_opmask_butone(0, SNO_NETWORK, "%s activating JUPE for %s, expiring "
                       "at %Tu: %s",
-#ifdef HEAD_IN_SAND_SNOTICES
-                      cli_name(sptr),
-#else
-                      IsServer(sptr) ? cli_name(sptr) :
-                      cli_name(cli_user(sptr)->server),
-#endif
+                       (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
+                         cli_name(sptr) :
+                         cli_name((cli_user(sptr))->server),
                       jupe->ju_server, jupe->ju_expire + TSoffset,
                       jupe->ju_reason);
 
@@ -221,12 +215,9 @@ jupe_deactivate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
   /* Inform ops and log it */
   sendto_opmask_butone(0, SNO_NETWORK, "%s %s JUPE for %s, expiring at %Tu: "
                       "%s",
-#ifdef HEAD_IN_SAND_SNOTICES
-                      cli_name(sptr),
-#else
-                      IsServer(sptr) ? cli_name(sptr) :
-                      cli_name(cli_user(sptr)->server),
-#endif
+                       (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
+                         cli_name(sptr) :
+                         cli_name((cli_user(sptr))->server),
                       JupeIsLocal(jupe) ? "removing local" : "deactivating",
                       jupe->ju_server, jupe->ju_expire + TSoffset,
                       jupe->ju_reason);
@@ -340,3 +331,19 @@ jupe_list(struct Client *sptr, char *server)
   /* end of jupe information */
   return send_reply(sptr, RPL_ENDOFJUPELIST);
 }
+
+int
+jupe_memory_count(size_t *ju_size)
+{
+  struct Jupe *jupe;
+  unsigned int ju = 0;
+
+  for (jupe = GlobalJupeList; jupe; jupe = jupe->ju_next)
+  {
+    ju++;
+    ju_size += sizeof(struct Jupe);
+    ju_size += jupe->ju_server ? (strlen(jupe->ju_server) + 1) : 0;
+    ju_size += jupe->ju_reason ? (strlen(jupe->ju_reason) + 1) : 0;
+  }
+  return ju;
+}
index 79dab30c1ad1ba66664e4ff557e3238e555c0182..10fe8406e11589591bfb1902783f02c08c34640c 100644 (file)
@@ -314,7 +314,7 @@ void remove_client_from_list(struct Client *cptr)
   assert(!cli_next(cptr) || cli_verify(cli_next(cptr)));
   assert(!IsMe(cptr));
 
-  /* Only try to remove cptr from the list if it IS in the list.
+  /* Only try remove cptr from the list if it IS in the list.
    * cli_next(cptr) cannot be NULL here, as &me is always the end
    * the list, and we never remove &me.    -GW 
    */
index 6959ff73acb05d1264bccdb069ab7fae6e055347..7b05e49eecb8af7c07c89bc464297c155c2d4b97 100644 (file)
@@ -34,6 +34,7 @@
 #include "s_bsd.h"
 #include "s_conf.h"
 #include "s_misc.h"
+#include "s_stats.h"
 #include "send.h"
 #include "sys.h"         /* MAXCLIENTS */
 
@@ -116,12 +117,20 @@ void count_listener_memory(int* count_out, size_t* size_out)
  * side effects - show ports
  * author       - Dianora
  */
-void show_ports(struct Client* sptr, int show_hidden, int port, int count)
+void show_ports(struct Client* sptr, struct StatDesc* sd, int stat,
+                char* param)
 {
-  struct Listener* listener = 0;
-  char             flags[8];
+  struct Listener *listener = 0;
+  char flags[8];
+  int show_hidden = IsOper(sptr);
+  int count = (IsOper(sptr) || MyUser(sptr)) ? 100 : 8;
+  int port = 0;
+
   assert(0 != sptr);
 
+  if (param)
+    port = atoi(param);
+
   for (listener = ListenerPollList; listener; listener = listener->next) {
     if (port && port != listener->port)
       continue;
@@ -441,9 +450,24 @@ static void accept_connection(struct Event* ev)
      * Thus no specific errors are tested at this
      * point, just assume that connections cannot
      * be accepted until some old is closed first.
+     *
+     * This piece of code implements multi-accept, based
+     * on the idea that poll/select can only be efficient,
+     * if we succeed in handling all available events,
+     * i.e. accept all pending connections.
+     *
+     * http://www.hpl.hp.com/techreports/2000/HPL-2000-174.html
      */
-    if (-1 == (fd = accept(listener->fd, (struct sockaddr*) &addr,
-                          &addrlen))) {
+    while (1)
+    {
+      if ((fd = accept(listener->fd, (struct sockaddr*) &addr, &addrlen))
+          == -1)
+      {
+        if (errno == EAGAIN ||
+#ifdef EWOULDBLOCK
+            errno == EWOULDBLOCK)
+#endif
+          return;
       /* Lotsa admins seem to have problems with not giving enough file
        * descriptors to their server so we'll add a generic warning mechanism
        * here.  If it turns out too many messages are generated for
@@ -452,38 +476,46 @@ static void accept_connection(struct Event* ev)
       sendto_opmask_butone(0, SNO_TCPCOMMON,
                           "Unable to accept connection: %m");
       return;
+      }
+      /*
+       * check for connection limit. If this fd exceeds the limit,
+       * all further accept()ed connections will also exceed it.
+       * Enable the server to clear out other connections before
+       * continuing to accept() new connections.
+       */
+      if (fd > MAXCLIENTS - 1)
+      {
+        ++ServerStats->is_ref;
+        send(fd, "ERROR :All connections in use\r\n", 32, 0);
+        close(fd);
+        return;
+      }
+      /*
+       * check to see if listener is shutting down. Continue
+       * to accept(), because it makes sense to clear our the
+       * socket's queue as fast as possible.
+       */
+      if (!listener->active)
+      {
+        ++ServerStats->is_ref;
+        send(fd, "ERROR :Use another port\r\n", 25, 0);
+        close(fd);
+        continue;
+      }
+      /*
+       * check to see if connection is allowed for this address mask
+       */
+      if (!connection_allowed((const char*) &addr,
+                              (const char*) &listener->mask))
+      {
+        ++ServerStats->is_ref;
+        send(fd, "ERROR :Use another port\r\n", 25, 0);
+        close(fd);
+        continue;
+      }
+      ++ServerStats->is_ac;
+      /* nextping = CurrentTime; */
+      add_connection(listener, fd);
     }
-    /*
-     * check for connection limit
-     */
-    if (fd > MAXCLIENTS - 1) {
-      ++ServerStats->is_ref;
-      send(fd, "ERROR :All connections in use\r\n", 32, 0);
-      close(fd);
-      return;
-    }
-    /*
-     * check to see if listener is shutting down
-     */
-    if (!listener->active) {
-      ++ServerStats->is_ref;
-      send(fd, "ERROR :Use another port\r\n", 25, 0);
-      close(fd);
-      return;
-    }
-    /*
-     * check to see if connection is allowed for this address mask
-     */
-    if (!connection_allowed((const char*) &addr,
-                           (const char*) &listener->mask)) {
-      ++ServerStats->is_ref;
-      send(fd, "ERROR :Use another port\r\n", 25, 0);
-      close(fd);
-      return;
-    }
-    ++ServerStats->is_ac;
-/*      nextping = CurrentTime; */
-
-    add_connection(listener, fd);
   }
 }
index f5615e5360f909be92af44a3214384cf27b8ab87..aa795ed8a09dafafd0968907a6287a4a4f9b092d 100644 (file)
@@ -120,8 +120,13 @@ int ms_account(struct Client* cptr, struct Client* sptr, int parc,
 
   assert(0 == cli_user(acptr)->account[0]);
 
+  if (strlen(parv[2]) > ACCOUNTLEN)
+    return protocol_violation(cptr,
+                              "Received account (%s) longer than %d for %s; "
+                              "ignoring.",
+                              parv[2], ACCOUNTLEN, cli_name(acptr));
   ircd_strncpy(cli_user(acptr)->account, parv[2], ACCOUNTLEN);
-  hide_hostmask(acptr, FLAGS_ACCOUNT);
+  hide_hostmask(acptr, FLAG_ACCOUNT);
 
   sendcmdto_serv_butone(sptr, CMD_ACCOUNT, cptr, "%C %s", acptr,
                        cli_user(acptr)->account);
index e9b44883fd70c2973ebccd73c291f3fc555161ac..dd8d0f4b4a3674759feb871e9736d4555df99c57 100644 (file)
@@ -84,7 +84,7 @@
 #include "client.h"
 #include "hash.h"
 #include "ircd.h"
-#include "ircd_policy.h"
+#include "ircd_features.h"
 #include "ircd_reply.h"
 #include "msg.h"
 #include "numeric.h"
@@ -115,10 +115,12 @@ static int send_admin_info(struct Client* sptr)
  */
 int m_admin(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
+  struct Client *acptr;
+
   assert(0 != cptr);
   assert(cptr == sptr);
 
-  if (parc > 1)
+  if (parc > 1  && (!(acptr = find_match_server(parv[1])) || !IsMe(acptr)))
     return send_reply(sptr, ERR_NOPRIVILEGES);
 
   return send_admin_info(sptr);
@@ -135,8 +137,8 @@ int mo_admin(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   assert(0 != cptr);
   assert(cptr == sptr);
 
-  if (hunt_server_cmd(sptr, CMD_ADMIN, cptr, HEAD_IN_SAND_REMOTE, ":%C", 1,
-                     parc, parv) != HUNTED_ISME)
+  if (hunt_server_cmd(sptr, CMD_ADMIN, cptr, feature_int(FEAT_HIS_REMOTE), 
+                      ":%C", 1, parc, parv) != HUNTED_ISME)
     return 0;
   return send_admin_info(sptr);
 }
diff --git a/ircd/m_asll.c b/ircd/m_asll.c
new file mode 100644 (file)
index 0000000..5da2c87
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * IRC - Internet Relay Chat, ircd/m_asll.c
+ * Copyright (C) 2002 Alex Badea <vampire@p16.pub.ro>
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+/*
+ * 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 "hash.h"
+#include "ircd.h"
+#include "ircd_reply.h"
+#include "ircd_string.h"
+#include "numeric.h"
+#include "numnicks.h"
+#include "match.h"
+#include "msg.h"
+#include "send.h"
+#include "s_bsd.h"
+#include "s_user.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+static int send_asll_reply(struct Client *from, struct Client *to, char *server,
+                          int rtt, int up, int down)
+{
+  sendcmdto_one(from, CMD_NOTICE, to,
+    (up || down) ? "%C :AsLL for %s -- RTT: %ims Upstream: %ims Downstream: %ims" :
+    rtt ? "%C :AsLL for %s -- RTT: %ims [no asymm info]" :
+    "%C :AsLL for %s -- [unknown]",
+    to, server, rtt, up, down);
+  return 0;
+}
+
+/*
+ * ms_asll - server message handler
+ */
+int ms_asll(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
+{
+  char *mask;
+  struct Client *acptr;
+  int i;
+
+  if (parc < 2)
+    return need_more_params(sptr, "ASLL");
+
+  if (parc > 5) {
+    if (!(acptr = findNUser(parv[1])))
+      return 0;
+    if (MyUser(acptr))
+      send_asll_reply(sptr, acptr, parv[2], atoi(parv[3]), atoi(parv[4]), atoi(parv[5]));
+    else
+      sendcmdto_prio_one(sptr, CMD_ASLL, acptr, "%C %s %s %s %s",
+        acptr, parv[2], parv[3], parv[4], parv[5]);
+    return 0;
+  }
+
+  if (hunt_server_prio_cmd(sptr, CMD_ASLL, cptr, 1, "%s %C", 2, parc, parv) != HUNTED_ISME)
+    return 0;
+  mask = parv[1];
+
+  for (i = 0; i <= HighestFd; i++) {
+    acptr = LocalClientArray[i];
+    if (!acptr || !IsServer(acptr) || !MyConnect(acptr) || match(mask, cli_name(acptr)))
+      continue;
+    sendcmdto_prio_one(&me, CMD_ASLL, sptr, "%C %s %i %i %i", sptr,
+      cli_name(acptr), cli_serv(acptr)->asll_rtt,
+      cli_serv(acptr)->asll_to, cli_serv(acptr)->asll_from);
+  }
+  return 0;
+}
+
+/*
+ * mo_asll - oper message handler
+ */
+int mo_asll(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
+{
+  char *mask;
+  struct Client *acptr;
+  int i;
+
+  if (parc < 2)
+    return need_more_params(sptr, "ASLL");
+
+  if (parc == 2 && MyUser(sptr))
+    parv[parc++] = cli_name(&me);
+
+  if (hunt_server_prio_cmd(sptr, CMD_ASLL, cptr, 1, "%s %C", 2, parc, parv) != HUNTED_ISME)
+    return 0;
+  mask = parv[1];
+
+  for (i = 0; i <= HighestFd; i++) {
+    acptr = LocalClientArray[i];
+    if (!acptr || !IsServer(acptr) || !MyConnect(acptr) || match(mask, cli_name(acptr)))
+      continue;
+    send_asll_reply(&me, sptr, cli_name(acptr), cli_serv(acptr)->asll_rtt,
+      cli_serv(acptr)->asll_to, cli_serv(acptr)->asll_from);
+  }
+  return 0;
+}
index b926a6aa0c2b3b97d2e5d08bccb2be7a5a2d663a..8718f0718231ad1efbe35b8d0d5a64197305c542 100644 (file)
@@ -153,12 +153,15 @@ static int user_set_away(struct User* user, char* message)
 int m_away(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   char* away_message = parv[1];
+  int was_away = cli_user(sptr)->away != 0;
 
   assert(0 != cptr);
   assert(cptr == sptr);
 
-  if (user_set_away(cli_user(sptr), away_message)) {
-    sendcmdto_serv_butone(sptr, CMD_AWAY, cptr, ":%s", away_message);
+  if (user_set_away(cli_user(sptr), away_message))
+  {
+    if (!was_away)    
+      sendcmdto_serv_butone(sptr, CMD_AWAY, cptr, ":%s", away_message);
     send_reply(sptr, RPL_NOWAWAY);
   }
   else {
index 15475b87ccc277b4b5d8eda1345bf41805b25df5..7726e7dc371f525d359253fc8bb22f97aaf1e700 100644 (file)
@@ -86,7 +86,7 @@
 #include "hash.h"
 #include "ircd.h"
 #include "ircd_alloc.h"
-#include "ircd_policy.h"
+#include "ircd_features.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "list.h"
@@ -178,7 +178,7 @@ int ms_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   struct ModeBuf modebuf, *mbuf = 0;
   struct Channel *chptr;
   time_t timestamp;
-  struct Membership *member;
+  struct Membership *member, *nmember;
   struct SLink *lp, **lp_p;
   unsigned int parse_flags = (MODE_PARSE_FORCE | MODE_PARSE_BURST);
   int param, nickpos = 0, banpos = 0;
@@ -198,11 +198,15 @@ int ms_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
      * than the burst TS (anti net.ride). The modes hack is here because
      * we have to do this before mode_parse, as chptr may go away.
      */
-    for (param = 3; param < parc; param++) {
+    for (param = 3; param < parc; param++)
+    {
       if (parv[param][0] != '+')
         continue;
-      if (strchr(parv[param], 'i') || strchr(parv[param], 'k')) {
-        for (member = chptr->members; member; member = member->next_member) {
+      if (strchr(parv[param], 'i') || strchr(parv[param], 'k'))
+      {
+        for (member = chptr->members; member; member = nmember)
+        {
+          nmember = member->next_member;
           if (!MyUser(member->user) || IsZombie(member))
             continue;
           sendcmdto_serv_butone(&me, CMD_KICK, NULL, "%H %C :Net Rider", chptr, member->user);
@@ -303,11 +307,9 @@ int ms_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
            newban = make_link(); /* create new ban */
 
            DupString(newban->value.ban.banstr, ban);
-#ifdef HEAD_IN_SAND_BANWHO
-           DupString(newban->value.ban.who, cli_name(&me));
-#else
-           DupString(newban->value.ban.who, cli_name(sptr));
-#endif
+
+            DupString(newban->value.ban.who, 
+                      cli_name(feature_bool(FEAT_HIS_BANWHO) ? &me : sptr));
            newban->value.ban.when = TStime();
 
            newban->flags = CHFL_BAN | CHFL_BURST_BAN; /* set flags */
index 9005bed9881999e95ec1a469d47f034f3a615699..ac164d2d97639bfbc85d8d41f9afbdc17078c08c 100644 (file)
@@ -95,6 +95,7 @@
 #include "msg.h"
 #include "numeric.h"
 #include "numnicks.h"
+#include "s_conf.h"
 #include "send.h"
 #include "support.h"
 
@@ -133,10 +134,6 @@ do_clearmode(struct Client *cptr, struct Client *sptr, struct Channel *chptr,
   struct SLink *link, *next;
   struct Membership *member;
 
-  /* Um...yeah, like it's supposed to have any modes at all. */
-  if (IsModelessChannel(chptr->chname))
-    return 0;
-
   /* Ok, so what are we supposed to get rid of? */
   for (; *control; control++) {
     for (flag_p = flags; flag_p[0]; flag_p += 2)
@@ -279,6 +276,8 @@ mo_clearmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   struct Channel *chptr;
   char *control = "ovpsmikbl"; /* default control string */
+  const char *chname, *qreason;
+  int force = 0;
 
   if (!feature_bool(FEAT_CONFIG_OPERCMDS))
     return send_reply(sptr, ERR_DISABLED, "CLEARMODE");
@@ -289,14 +288,28 @@ mo_clearmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   if (parc > 2)
     control = parv[2];
 
+  chname = parv[1];
+  if (*chname == '!')
+  {
+    chname++;
+    if (!HasPriv(sptr, IsLocalChannel(chname) ?
+                         PRIV_FORCE_LOCAL_OPMODE :
+                         PRIV_FORCE_OPMODE))
+      return send_reply(sptr, ERR_NOPRIVILEGES);
+    force = 1;
+  }
+
   clean_channelname(parv[1]);
 
   if (!HasPriv(sptr,
               IsLocalChannel(parv[1]) ? PRIV_LOCAL_OPMODE : PRIV_OPMODE))
     return send_reply(sptr, ERR_NOPRIVILEGES);
 
-  if (('#' != *parv[1] && '&' != *parv[1]) || !(chptr = FindChannel(parv[1])))
-    return send_reply(sptr, ERR_NOSUCHCHANNEL, parv[1]);
+  if (('#' != *chname && '&' != *chname) || !(chptr = FindChannel(chname)))
+    return send_reply(sptr, ERR_NOSUCHCHANNEL, chname);
+  if (!force && (qreason = find_quarantine(chptr->chname)))
+    return send_reply(sptr, ERR_QUARANTINED, chptr->chname, qreason);
+
 
   return do_clearmode(cptr, sptr, chptr, control);
 }
index 7f8689c9b035e553e4eddc3fbd164a66c9adb828..f496aae1a49c87edf803bb9f831a9fa95b063500 100644 (file)
@@ -122,9 +122,6 @@ int ms_create(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 
   chanTS = atoi(parv[2]);
 
-  joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0);
-  joinbuf_init(&create, sptr, cptr, JOINBUF_TYPE_CREATE, 0, chanTS);
-
   /* A create that didn't appear during a burst has that servers idea of
    * the current time.  Use it for lag calculations.
    */
@@ -133,18 +130,28 @@ int ms_create(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     cli_serv(cli_user(sptr)->server)->lag = TStime() - chanTS;
 
   /* If this server is >1 minute fast, warn */
-  if (TStime() - chanTS<-60) {
+  if (TStime() - chanTS<-60)
+  {
     static time_t rate;
     sendto_opmask_butone_ratelimited(0, SNO_NETWORK, &rate,
-                                    "Timestamp drift from %C (%is)",
+                                     "Timestamp drift from %C (%is); issuing "
+                                     "SETTIME to correct this",
                                     cli_user(sptr)->server,
                                     chanTS - TStime());
-
     /* If this server is >5 minutes fast, squit it */
     if (TStime() - chanTS<-5*60*60)
       return exit_client(sptr, sptr, &me, "Timestamp Drift/Bogus TS");
+    /* Now issue a SETTIME to resync.  If we're in the wrong, our
+     * (RELIABLE_CLOCK) hub will bounce a SETTIME back to us.
+     */
+    sendcmdto_prio_one(&me, CMD_SETTIME, cli_user(sptr)->server,
+                       "%Tu %C", TStime(), cli_user(sptr)->server);
   }
 
+  joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0);
+  joinbuf_init(&create, sptr, cptr, JOINBUF_TYPE_CREATE, 0, chanTS);
+
+  
   /* For each channel in the comma seperated list: */
   for (name = ircd_strtok(&p, parv[1], ","); name;
        name = ircd_strtok(&p, 0, ",")) {
@@ -153,7 +160,8 @@ int ms_create(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     if (IsLocalChannel(name))
       continue;
 
-    if ((chptr = FindChannel(name))) {
+    if ((chptr = FindChannel(name)))
+    {
       name = chptr->chname;
 
       /* Check if we need to bounce a mode */
@@ -171,15 +179,15 @@ int ms_create(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 
        badop = 1;
       }
-    } else                        /* Channel doesn't exist: create it */
+    }
+    else /* Channel doesn't exist: create it */
       chptr = get_channel(sptr, name, CGT_CREATE);
 
     if (!badop) /* Set/correct TS */
       chptr->creationtime = chanTS;
 
     joinbuf_join(badop ? &join : &create, chptr,
-                (badop || IsModelessChannel(name)) ?
-                CHFL_DEOPPED : CHFL_CHANOP);
+                (badop || CHFL_CHANOP));
   }
 
   joinbuf_flush(&join); /* flush out the joins and creates */
index e0d0f9aaf560ebbc15c36c6d415f7a3163a5d1de..cee85ac400df69597cf3903a97ca4589efdbc12a 100644 (file)
@@ -126,25 +126,29 @@ ms_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   struct Gline *agline;
   unsigned int flags = 0;
   time_t expire_off, lastmod = 0;
-  char *mask = parv[2], *target = parv[1], *reason;
+  char *mask = parv[2], *target = parv[1], *reason = "No reason";
 
-  if (*mask == '!') {
+  if (*mask == '!')
+  {
     mask++;
-
-    if (HasPriv(sptr, PRIV_WIDE_GLINE))
-      flags |= GLINE_OPERFORCE;
+    flags |= GLINE_OPERFORCE;
   }
 
-  if ((parc == 3 && *mask == '-') || parc == 5) {
+  if ((parc == 3 && *mask == '-') || parc == 5)
+  {
     if (!find_conf_byhost(cli_confs(cptr), cli_name(sptr), CONF_UWORLD))
       return need_more_params(sptr, "GLINE");
 
-    reason = parv[4];
+    if (parc > 4)
+      reason = parv[4];
     flags |= GLINE_FORCE;
-  } else if (parc > 5) {
+  }
+  else if (parc > 5)
+  {
     lastmod = atoi(parv[4]);
     reason = parv[5];
-  } else
+  }
+  else
     return need_more_params(sptr, "GLINE");
 
   if (!(target[0] == '*' && target[1] == '\0')) {
@@ -263,12 +267,16 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   } else
     return need_more_params(sptr, "GLINE");
 
-  if (target) {
-    if (!(target[0] == '*' && target[1] == '\0')) {
+  if (target)
+  {
+    if (!(target[0] == '*' && target[1] == '\0'))
+    {
       if (!(acptr = find_match_server(target)))
        return send_reply(sptr, ERR_NOSUCHSERVER, target);
 
-      if (!IsMe(acptr)) { /* manually propagate, since we don't set it */
+      /* manually propagate, since we don't set it */
+      if (!IsMe(acptr))
+      {
        if (!feature_bool(FEAT_CONFIG_OPERCMDS))
          return send_reply(sptr, ERR_DISABLED, "GLINE");
 
@@ -280,12 +288,9 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
                      flags & GLINE_ACTIVE ? '+' : '-', mask, parv[3],
                      TStime(), reason);
        return 0;
-      } else if (!HasPriv(sptr, PRIV_LOCAL_GLINE))
-       return send_reply(sptr, ERR_NOPRIVILEGES);
-
+      }
       flags |= GLINE_LOCAL;
-    } else if (!HasPriv(sptr, PRIV_GLINE))
-      return send_reply(sptr, ERR_NOPRIVILEGES);
+    }
   }
 
   if (!(flags & GLINE_LOCAL) && !feature_bool(FEAT_CONFIG_OPERCMDS))
@@ -293,6 +298,9 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
 
   agline = gline_find(mask, GLINE_ANY | GLINE_EXACT);
 
+  if (!HasPriv(sptr, (flags & GLINE_LOCAL ? PRIV_LOCAL_GLINE : PRIV_GLINE)))
+    return send_reply(sptr, ERR_NOPRIVILEGES);
+
   if (agline) {
     if (GlineIsLocal(agline) && !(flags & GLINE_LOCAL)) /* global over local */
       gline_free(agline);
index 7b0b493ae56c8b026963324917cba7dc0e3735e5..ca5401e0489e09e808a6235ff06e795b3f735579 100644 (file)
@@ -146,7 +146,8 @@ int m_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     return 0;
 
   if (!(chptr = FindChannel(parv[2]))) {
-    if (IsModelessChannel(parv[2]) || IsLocalChannel(parv[2])) {
+    if (IsLocalChannel(parv[2]))
+    {
       send_reply(sptr, ERR_NOTONCHANNEL, parv[2]);
       return 0;
     }
@@ -195,7 +196,7 @@ int m_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   if (MyConnect(acptr))
     add_invite(acptr, chptr);
 
-  if (!IsLocalChannel(chptr->chname))
+  if (!IsLocalChannel(chptr->chname) || MyConnect(acptr))
     sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%H", cli_name(acptr), chptr);
 
   return 0;
index 8843b5d3d2baf716b20bcb592d26ba6e33cb3ce5..d2bfcfecabce299f1d6b4503f1279bc1f82d306b 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-/*
- * Helper function to see if there are any control characters
- * in a given string
- */
-static char *
-HasControlChars(char *mstring)
-{
-  unsigned char *j;
-  for(j = mstring; *j ; j++) {
-    if(*j <= 32) { return j; }
-  }
-
-  return 0;
-}
-
 /*
  * Helper function to find last 0 in a comma-separated list of
  * channel names.
@@ -185,7 +170,7 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   struct ModeBuf mbuf;
   struct Gline *gline;
   unsigned int flags = 0;
-  int i;
+  int i, j, k = 0;
   char *p = 0;
   char *chanlist;
   char *name;
@@ -208,7 +193,21 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
     if (join0(&join, cptr, sptr, name)) /* did client do a JOIN 0? */
       continue;
 
-    if (!IsChannelName(name) || HasControlChars(name)) { /* bad channel name */
+    if (!IsChannelName(name))
+    {
+      /* bad channel name */
+      send_reply(sptr, ERR_NOSUCHCHANNEL, name);
+      continue;
+    }
+
+    /* This checks if the channel contains control codes and rejects em
+     * until they are gone, then we will do it otherwise - *SOB Mode*
+     */
+    for (k = 0, j = 0; name[j]; j++)
+      if (IsCntrl(name[j]))
+        k++;
+    if (k > 0)
+    {
       send_reply(sptr, ERR_NOSUCHCHANNEL, name);
       continue;
     }
@@ -220,13 +219,15 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
       continue;
     }
 
-    if ((chptr = FindChannel(name))) {
+    if ((chptr = FindChannel(name)))
+    {
       if (find_member_link(chptr, sptr))
        continue; /* already on channel */
 
       flags = CHFL_DEOPPED;
-    } else
-      flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
+    }
+    else
+      flags = CHFL_CHANOP;
 
     if (cli_user(sptr)->joined >= feature_int(FEAT_MAXCHANNELSPERUSER) &&
        !HasPriv(sptr, PRIV_CHAN_LIMIT)) {
@@ -253,31 +254,43 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
       if (check_target_limit(sptr, chptr, chptr->chname, 0))
        continue; /* exceeded target limit */
       else if (!is_level0_op && (i = can_join(sptr, chptr, keys))) {
-       if (i > MAGIC_OPER_OVERRIDE) { /* oper overrode mode */
-         switch (i - MAGIC_OPER_OVERRIDE) {
-         case ERR_CHANNELISFULL: /* figure out which mode */
-           i = 'l';
-           break;
-
-         case ERR_INVITEONLYCHAN:
-           i = 'i';
-           break;
-
-         case ERR_BANNEDFROMCHAN:
-           i = 'b';
-           break;
-
-         case ERR_BADCHANNELKEY:
-           i = 'k';
-           break;
-         }
-
-         /* send accountability notice */
-         sendto_opmask_butone(0, SNO_HACK4, "OPER JOIN: %C JOIN %H "
-                              "(overriding +%c)", sptr, chptr, i);
-       } else {
-         send_reply(sptr, i, chptr->chname);
-         continue;
+       if (i > MAGIC_OPER_OVERRIDE)
+        { /* oper overrode mode */
+          switch (i - MAGIC_OPER_OVERRIDE)
+          {
+          case ERR_CHANNELISFULL: /* figure out which mode */
+            i = 'l';
+            break;
+
+          case ERR_INVITEONLYCHAN:
+            i = 'i';
+            break;
+
+          case ERR_BANNEDFROMCHAN:
+            i = 'b';
+            break;
+
+          case ERR_BADCHANNELKEY:
+            i = 'k';
+            break;
+
+          case ERR_NEEDREGGEDNICK:
+            i = 'r';
+            break;
+
+          default:
+            i = '?';
+            break;
+          }
+
+          /* send accountability notice */
+          sendto_opmask_butone(0, SNO_HACK4, "OPER JOIN: %C JOIN %H "
+                               "(overriding +%c)", sptr, chptr, i);
+        }
+        else
+        {
+          send_reply(sptr, i, chptr->chname);
+          continue;
        }
       } /* else if ((i = can_join(sptr, chptr, keys))) */
 
@@ -294,12 +307,14 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
       }
     } else if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
       continue; /* couldn't get channel */
-    else if (check_target_limit(sptr, chptr, chptr->chname, 1)) {
+    else if (check_target_limit(sptr, chptr, chptr->chname, 1))
+    {
       /* Note: check_target_limit will only ever return 0 here */
       chptr->members = 0;
       destruct_channel(chptr); /* created it... */
       continue;
-    } else
+    }
+    else
       joinbuf_join(&create, chptr, flags | CHFL_CHANNEL_MANAGER);
 
     del_invite(sptr, chptr);
@@ -333,8 +348,14 @@ int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   char *chanlist;
   char *name;
 
-  if (IsServer(sptr)) {
-    return protocol_violation(sptr,"%s tried to JOIN a channel, duh!", cli_name(sptr));
+  if (IsServer(sptr))
+  {
+    return protocol_violation(cptr,
+                              "%s tried to JOIN %s, duh!",
+                              cli_name(sptr),
+                              (parc < 2 || *parv[1] == '\0') ? "a channel" :
+                                                               parv[1]
+                              );
   }
 
   if (parc < 2 || *parv[1] == '\0')
@@ -354,25 +375,29 @@ int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
     if (join0(&join, cptr, sptr, name)) /* did client do a JOIN 0? */
       continue;
 
-    if (IsLocalChannel(name) || !IsChannelName(name)) {
-      protocol_violation(sptr,"%s tried to join %s",cli_name(cptr),name);
+    if (IsLocalChannel(name) || !IsChannelName(name))
+    {
+      protocol_violation(cptr, "%s tried to join %s", cli_name(sptr), name);
       continue;
     }
 
-    if (!(chptr = FindChannel(name))) {
+    if (!(chptr = FindChannel(name)))
+    {
       /* No channel exists, so create one */
-      if (!(chptr = get_channel(sptr, name, CGT_CREATE))) {
+      if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
+      {
         protocol_violation(sptr,"couldn't get channel %s for %s",
                           name,cli_name(sptr));
        continue;
       }
-      flags = CHFL_DEOPPED | ((cli_flags(sptr) & FLAGS_TS8) ? CHFL_SERVOPOK : 0);
+      flags = CHFL_DEOPPED | (HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0);
 
       /* when the network is 2.10.11+ then remove MAGIC_REMOTE_JOIN_TS */ 
       chptr->creationtime = creation ? creation : MAGIC_REMOTE_JOIN_TS;
     }
     else { /* We have a valid channel? */
-      if ((member = find_member_link(chptr, sptr))) {
+      if ((member = find_member_link(chptr, sptr)))
+      {
        /* It is impossible to get here --Run */
        if (!IsZombie(member)) /* already on channel */
          continue;
@@ -380,8 +405,9 @@ int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
        flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK);
        remove_user_from_channel(sptr, chptr);
        chptr = FindChannel(name);
-      } else
-       flags = CHFL_DEOPPED | ((cli_flags(sptr) & FLAGS_TS8) ? CHFL_SERVOPOK : 0);
+      }
+      else
+        flags = CHFL_DEOPPED | (HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0);
       /* Always copy the timestamp when it is older, that is the only way to
          ensure network-wide synchronization of creation times. */
       if (creation && creation < chptr->creationtime)
index 4a7200590382fcb8cbd4d985a7cc32aa1be98470..4aed6113a294baf7873357eee5f5198eb08e4b38 100644 (file)
@@ -110,7 +110,7 @@ int m_kick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   struct Membership* member2;
   char *name, *comment;
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   if (parc < 3 || *parv[1] == '\0')
     return need_more_params(sptr, "KICK");
@@ -122,7 +122,7 @@ int m_kick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
     return send_reply(sptr, ERR_NOSUCHCHANNEL, name);
 
   if (!(member2 = find_member_link(chptr, sptr)) || IsZombie(member2)
-      || !IsChanOp(member2) || IsModelessChannel(name))
+      || !IsChanOp(member2))
     return send_reply(sptr, ERR_CHANOPRIVSNEEDED, name);
 
   if (!(who = find_chasing(sptr, parv[2], 0)))
@@ -176,7 +176,7 @@ int ms_kick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   struct Membership *member = 0, *sptr_link = 0;
   char *name, *comment;
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   if (parc < 3 || *parv[1] == '\0')
     return need_more_params(sptr, "KICK");
@@ -195,7 +195,10 @@ int ms_kick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
     member = 0;
 
   /* Send HACK notice, but not for servers in BURST */
-  if (IsServer(sptr) && !IsBurstOrBurstAck(sptr))
+  /* 2002-10-17: Don't send HACK if the users local server is kicking them */
+  if (IsServer(sptr) &&
+      !IsBurstOrBurstAck(sptr) &&
+      sptr!=cli_from(who))
     sendto_opmask_butone(0, SNO_HACK4, "HACK: %C KICK %H %C %s", sptr, chptr,
                         who, comment);
 
index 1a47c9bff00e5744dea157390da94619f4044bf4..4f7f7fb2212ddebc388ff1fa2b7cfaefba00f283 100644 (file)
@@ -84,8 +84,8 @@
 #include "client.h"
 #include "hash.h"
 #include "ircd.h"
+#include "ircd_features.h"
 #include "ircd_log.h"
-#include "ircd_policy.h"
 #include "ircd_reply.h"
 #include "ircd_snprintf.h"
 #include "ircd_string.h"
  *
  */
 static int do_kill(struct Client* cptr, struct Client* sptr,
-                  struct Client* victim, char* inpath, char* path, char *msg)
+                  struct Client* victim, char* inpath, char* path, charmsg)
 {
   assert(0 != cptr);
   assert(0 != sptr);
-  assert(IsUser(victim));
+  assert(!IsServer(victim));
 
   /*
    * Notify all *local* opers about the KILL (this includes the one
@@ -135,11 +135,11 @@ static int do_kill(struct Client* cptr, struct Client* sptr,
                           inpath, path, msg);
 
     /*
-     * Set FLAGS_KILLED. This prevents exit_one_client from sending
+     * Set FLAG_KILLED. This prevents exit_one_client from sending
      * the unnecessary QUIT for this. (This flag should never be
      * set in any other place)
      */
-    cli_flags(victim) |= FLAGS_KILLED;
+    SetFlag(victim, FLAG_KILLED);
   }
 
   /*
@@ -150,19 +150,15 @@ static int do_kill(struct Client* cptr, struct Client* sptr,
    * In accordance with the new hiding rules, the victim
    * always sees the kill as coming from me.
    */
-#ifdef HEAD_IN_SAND_KILLWHO
   if (MyConnect(victim))
-    sendcmdto_one(&me, CMD_KILL, victim, "%C :%s %s", victim,
-                  HEAD_IN_SAND_SERVERNAME, msg);
-  return exit_client_msg(cptr, victim, &me, "Killed (%s %s)",
-                        HEAD_IN_SAND_SERVERNAME, msg);
-#else
-  if (MyConnect(victim))
-    sendcmdto_one(sptr, CMD_KILL, victim, "%C :%s %s", victim,
-                  cli_name(sptr), msg);
-  return exit_client_msg(cptr, victim, sptr, "Killed (%s %s)", cli_name(sptr),
+    sendcmdto_one(feature_bool(FEAT_HIS_KILLWHO) ? &me : sptr, CMD_KILL, 
+                 victim, "%C :%s %s", victim, feature_bool(FEAT_HIS_KILLWHO)
+                 ? feature_str(FEAT_HIS_SERVERNAME) : cli_name(sptr), msg);
+  return exit_client_msg(cptr, victim, feature_bool(FEAT_HIS_KILLWHO)
+                        ? &me : sptr, "Killed (%s %s)",
+                        feature_bool(FEAT_HIS_KILLWHO) ? 
+                        feature_str(FEAT_HIS_SERVERNAME) : cli_name(sptr),
                         msg);
-#endif
 }
 
 /*
index 60cd7d388411ae515a3712a3ad65e38e25ed4ffb..63f615db8639600c5f3649626a909d096d9cc6fa 100644 (file)
@@ -84,7 +84,7 @@
 #include "client.h"
 #include "ircd.h"
 #include "ircd_defs.h"
-#include "ircd_policy.h"
+#include "ircd_features.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "match.h"
 int m_links(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   char *mask;
-  struct Client *acptr = 0;
+  struct Client *acptr;
+
+  if (feature_bool(FEAT_HIS_LINKS) && !IsAnOper(sptr))
+  {
+    send_reply(sptr, RPL_ENDOFLINKS, parc < 2 ? "*" : parv[1]);
+    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s %s", sptr,
+                  "/LINKS has been disabled, from CFV-165.  Visit ", 
+                  feature_str(FEAT_HIS_URLSERVERS));
+    return 0;
+  }
 
   if (parc > 2)
   {
@@ -141,24 +150,45 @@ int m_links(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   return 0;
 }
 
-#ifdef HEAD_IN_SAND_LINKS
-int m_links_redirect(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
-{
-  if (parc > 2)
-    return send_reply(cptr, ERR_NOPRIVILEGES);
-
-  map_dump_links_head_in_sand(sptr, parv[1]);
-
-  send_reply(sptr, RPL_ENDOFLINKS, BadPtr(parv[1]) ? "*" : parv[1]);
-
-  return 0;
-}
-
-#endif HEAD_IN_SAND_LINKS
-
-
-
-
-
-
-
+/*
+ * ms_links - server message handler
+ *
+ * parv[0] = sender prefix
+ * parv[1] = servername mask
+ *
+ * or
+ *
+ * parv[0] = sender prefix
+ * parv[1] = server to query
+ * parv[2] = servername mask
+ */
+int
+ms_links(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
+ {
+   char *mask;
+   struct Client *acptr;
+
+   if (parc > 2)
+   {
+     if (hunt_server_cmd(sptr, CMD_LINKS, cptr, 1, "%C :%s", 1, parc, parv) !=
+         HUNTED_ISME)
+       return 0;
+     mask = parv[2];
+   }
+   else
+     mask = parc < 2 ? 0 : parv[1];
+   for (acptr = GlobalClientList, collapse(mask); acptr; acptr = cli_next(acptr))
+   {
+     if (!IsServer(acptr) && !IsMe(acptr))
+       continue;
+     if (!BadPtr(mask) && match(mask, cli_name(acptr)))
+       continue;
+     send_reply(sptr, RPL_LINKS, cli_name(acptr), cli_name(cli_serv(acptr)->up),
+                cli_hopcount(acptr), cli_serv(acptr)->prot,
+                ((cli_info(acptr))[0] ? cli_info(acptr) : "(Unknown Location)"));
+   }
+   send_reply(sptr, RPL_ENDOFLINKS, BadPtr(mask) ? "*" : mask);
+   return 0;
+ }
index 02da8d7b6d1632441b11980c87273f6c6c32b3f8..04092359e92d324a6ddf5efc7975a87adb1863b4 100644 (file)
@@ -107,8 +107,8 @@ int m_lusers(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   int longoutput = MyUser(sptr) || IsOper(sptr);
   if (parc > 2)
-    if (hunt_server_cmd(sptr, CMD_LUSERS, cptr, HEAD_IN_SAND_REMOTE, "%s :%C",
-                       2, parc, parv) != HUNTED_ISME)
+    if (hunt_server_cmd(sptr, CMD_LUSERS, cptr, feature_int(FEAT_HIS_REMOTE),
+                        "%s :%C", 2, parc, parv) != HUNTED_ISME)
       return 0;
 
   send_reply(sptr, RPL_LUSERCLIENT, UserStats.clients - UserStats.inv_clients,
index 1e4e48b097ff6bdb10d9cf087a06f8d700124f7d..fb9897f01c103d7cd079383b367650119e7c8c7b 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+static void dump_map(struct Client *cptr, struct Client *server, char *mask, int prompt_length)
+{
+  const char *chr;
+  static char prompt[64];
+  struct DLink *lp;
+  char *p = prompt + prompt_length;
+  int cnt = 0;
+  
+  *p = '\0';
+  if (prompt_length > 60)
+    send_reply(cptr, RPL_MAPMORE, prompt, cli_name(server));
+  else
+  {
+    char lag[512];
+    if (cli_serv(server)->lag>10000)
+      lag[0]=0;
+    else if (cli_serv(server)->lag<0)
+      strcpy(lag,"(0s)");
+    else
+      sprintf(lag,"(%is)",cli_serv(server)->lag);
+    if (IsBurst(server))
+      chr = "*";
+    else if (IsBurstAck(server))
+      chr = "!";
+    else
+      chr = "";
+    send_reply(cptr, RPL_MAP, prompt, chr, cli_name(server),
+               lag, (server == &me) ? UserStats.local_clients :
+                                      cli_serv(server)->clients);
+  }
+  if (prompt_length > 0)
+  {
+    p[-1] = ' ';
+    if (p[-2] == '`')
+      p[-2] = ' ';
+  }
+  if (prompt_length > 60)
+    return;
+  strcpy(p, "|-");
+  for (lp = cli_serv(server)->down; lp; lp = lp->next)
+    if (match(mask, cli_name(lp->value.cptr)))
+      ClrFlag(lp->value.cptr, FLAG_MAP);
+    else
+    {
+      SetFlag(lp->value.cptr, FLAG_MAP);
+      cnt++;
+    }
+  for (lp = cli_serv(server)->down; lp; lp = lp->next)
+  {
+    if (!HasFlag(lp->value.cptr, FLAG_MAP))
+      continue;
+    if (--cnt == 0)
+      *p = '`';
+    dump_map(cptr, lp->value.cptr, mask, prompt_length + 2);
+  }
+  if (prompt_length > 0)
+    p[-1] = '-';
+}
+
+
 /*
  * m_map - generic message handler
  * -- by Run
  */
 int m_map(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
-#ifdef HEAD_IN_SAND_MAP
-  map_dump_head_in_sand(sptr);
-#else
-  if(parc < 2)
+  if (feature_bool(FEAT_HIS_MAP) && !IsAnOper(sptr))
+  {
+    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s %s", sptr,
+                  "/MAP has been disabled, from CFV-165.  "
+                  "Visit ", feature_str(FEAT_HIS_URLSERVERS));
+    return 0;
+  }
+  if (parc < 2)
     parv[1] = "*";
-  map_dump(sptr, &me, parv[1], 0);
-#endif /* HEAD_IN_SAND_MAP */
+  dump_map(sptr, &me, parv[1], 0);
   send_reply(sptr, RPL_MAPEND);
 
   return 0;
@@ -128,7 +191,7 @@ int mo_map(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   if (parc < 2)
     parv[1] = "*";
 
-  map_dump(sptr, &me, parv[1], 0);
+  dump_map(sptr, &me, parv[1], 0);
   send_reply(sptr, RPL_MAPEND);
 
   return 0;
index 474f39b3f3f9fd1b8ae5840b49cb3c1d72263fbc..362bc76aed4a6e5b75e79a4561992fd21d6e516b 100644 (file)
@@ -112,11 +112,10 @@ m_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
 
   clean_channelname(parv[1]);
 
-  if (('#' != *parv[1] && '&' != *parv[1] && '+' != *parv[1]) || 
-      !(chptr = FindChannel(parv[1])))
+  if (!IsChannelName(parv[1]) || !(chptr = FindChannel(parv[1])))
     return set_user_mode(cptr, sptr, parc, parv);
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   member = find_member_link(chptr, sptr);
 
@@ -168,10 +167,11 @@ ms_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   if (IsLocalChannel(parv[1]))
     return 0;
 
-  if (('#' != *parv[1] && '+' != *parv[1])|| !(chptr = FindChannel(parv[1])))
+  if (IsChannelName(parv[1]) || !(chptr = FindChannel(parv[1])) ||
+      IsLocalChannel(parv[1]))
     return set_user_mode(cptr, sptr, parc, parv);
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   if (IsServer(sptr)) {
     if (find_conf_byhost(cli_confs(cptr), cli_name(sptr), CONF_UWORLD))
index b33cfd26c02139285fbc1b8308c331ceb92dede6..e2cd87ded6c2369bf307bcf2f36e027687abfbd4 100644 (file)
@@ -83,7 +83,7 @@
 
 #include "client.h"
 #include "ircd.h"
-#include "ircd_policy.h"
+#include "ircd_features.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "match.h"
  */
 int m_motd(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
-  if (hunt_server_cmd(sptr, CMD_MOTD, cptr, HEAD_IN_SAND_REMOTE, "%C", 1,
+  if (hunt_server_cmd(sptr, CMD_MOTD, cptr, feature_int(FEAT_HIS_REMOTE), "%C", 1,
                      parc, parv) != HUNTED_ISME)
     return 0;
 
index 01df99181ae0892a2b33c05f5b0da1d5c71322df..b15f10559cea2f0f2c3f1482b9be7a33ade649eb 100644 (file)
@@ -335,6 +335,7 @@ int m_names(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
        *  non secret channels.
        */ 
       do_names(sptr, chptr, NAMES_VIS);
+      send_reply(sptr, RPL_ENDOFNAMES, para);
     } 
   } else { /* Channel doesn't exist. */ 
       send_reply(sptr, RPL_ENDOFNAMES, para); 
index 06287ddd5b36fa512a43a93c86b60584173c4b1b..48e022c2cf0160e33f50d1c94629de90c8af9926 100644 (file)
@@ -86,9 +86,9 @@
 #include "hash.h"
 #include "ircd.h"
 #include "ircd_chattr.h"
+#include "ircd_features.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
-#include "ircd_policy.h"
 #include "msg.h"
 #include "numeric.h"
 #include "numnicks.h"
 #include <stdlib.h>
 #include <string.h>
 
+ /*
+* 'do_nick_name' ensures that the given parameter (nick) is really a proper
+* string for a nickname (note, the 'nick' may be modified in the process...)
+*
+* RETURNS the length of the final NICKNAME (0, if nickname is invalid)
+*
+* Nickname characters are in range 'A'..'}', '_', '-', '0'..'9'
+*  anything outside the above set will terminate nickname.
+* In addition, the first character cannot be '-' or a Digit.
+*
+* Note:
+*  The '~'-character should be allowed, but a change should be global,
+*  some confusion would result if only few servers allowed it...
+*/
+static int do_nick_name(char* nick)
+{
+  char* ch  = nick;
+  char* end = ch + NICKLEN;
+  assert(0 != ch);
+  
+  /* first character in [0..9-] */
+  if (*ch == '-' || IsDigit(*ch))
+    return 0;
+  for ( ; (ch < end) && *ch; ++ch)
+    if (!IsNickChar(*ch))
+      break;
+
+  *ch = '\0';
+
+  return (ch - nick);
+}
+
 /*
  * m_nick - message handler for local clients
  * parv[0] = sender prefix
@@ -140,10 +172,7 @@ int m_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   strcpy(nick, arg);
 
   /*
-   * If do_nick_name() returns a null name OR if the server sent a nick
-   * name and do_nick_name() changed it in some way (due to rules of nick
-   * creation) then reject it. If from a server and we reject it,
-   * and KILL it. -avalon 4/4/92
+   * If do_nick_name() returns a null name then reject it.
    */
   if (0 == do_nick_name(nick)) {
     send_reply(sptr, ERR_ERRONEUSNICKNAME, arg);
@@ -209,6 +238,11 @@ int m_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
    * "dormant nick" way of generating collisions...
    *
    * XXX - hmmm can this happen after one is registered?
+   *
+   * Yes, client 1 connects to IRC and registers, client 2 connects and
+   * sends "NICK foo" but doesn't send anything more.  client 1 now does
+   * /nick foo, they should succeed and client 2 gets disconnected with
+   * the message below.
    */
   if (IsUnknown(acptr) && MyConnect(acptr)) {
     ++ServerStats->is_ref;
@@ -418,11 +452,11 @@ int ms_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       sendcmdto_serv_butone(&me, CMD_KILL, cptr, "%s :%s (%s)",
                             nick, cli_name(&me), type);
       /* Don't go sending off a QUIT message... */
-      cli_flags(sptr) |= FLAGS_KILLED;
+      SetFlag(sptr, FLAG_KILLED);
       /* Remove them locally. */
       exit_client_msg(cptr, sptr, &me,
-                      "Killed (" HEAD_IN_SAND_SERVERNAME " (Nick collision))",
-                      type);
+                      "Killed (%s (%s))",
+                      feature_str(FEAT_HIS_SERVERNAME), type);
       /*
        * We have killed sptr off, zero out it's pointer so if it's used
        * again we'll know about it --Bleep
@@ -439,14 +473,15 @@ int ms_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   send_reply(acptr, ERR_NICKCOLLISION, nick);
 
   ServerStats->is_kill++;
-  cli_flags(acptr) |= FLAGS_KILLED;
+  SetFlag(acptr, FLAG_KILLED);
   /*
    * This exits the client we had before getting the NICK message
    */
-  sendcmdto_serv_butone(&me, CMD_KILL, NULL, "%C :" HEAD_IN_SAND_SERVERNAME
-                        " (%s)", acptr, type);
-  exit_client_msg(cptr, acptr, &me, "Killed (" HEAD_IN_SAND_SERVERNAME " (%s))",
-                  type);
+  sendcmdto_serv_butone(&me, CMD_KILL, NULL, "%C :%s"
+                        " (%s)", acptr, feature_str(FEAT_HIS_SERVERNAME),
+                        type);
+  exit_client_msg(cptr, acptr, &me, "Killed (%s (%s))",
+                  feature_str(FEAT_HIS_SERVERNAME), type);
   if (lastnick == cli_lastnick(acptr))
     return 0;
   if (sptr == NULL)
index b195172d993decdd3cebac7e2027b589092b853d..09d68a70f0aff780c7f853c3736bcb89d7dc6d32 100644 (file)
@@ -112,7 +112,7 @@ int m_notice(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   assert(0 != cptr);
   assert(cptr == sptr);
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   if (parc < 2 || EmptyString(parv[1]))
     return send_reply(sptr, ERR_NORECIPIENT, MSG_NOTICE);
@@ -155,7 +155,7 @@ int ms_notice(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   char* name;
   char* server;
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   if (parc < 3) {
     /*
@@ -202,7 +202,7 @@ int mo_notice(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   assert(0 != cptr);
   assert(cptr == sptr);
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   if (parc < 2 || EmptyString(parv[1]))
     return send_reply(sptr, ERR_NORECIPIENT, MSG_NOTICE);
index 1166840c5e77ae41993503721a51f6d59d7662c8..d334d68e41e6ba6cb31ced72ed19cf3233b4e95a 100644 (file)
@@ -143,7 +143,8 @@ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     aconf = find_conf_exact(name, cli_username(sptr),
                             ircd_ntoa((const char*) &(cli_ip(cptr))), CONF_OPS);
 
-  if (!aconf || IsIllegal(aconf)) {
+  if (!aconf || IsIllegal(aconf))
+  {
     send_reply(sptr, ERR_NOOPERHOST);
     sendto_opmask_butone(0, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s)",
                         parv[0], cli_user(sptr)->username, cli_sockhost(sptr));
@@ -151,8 +152,9 @@ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   }
   assert(0 != (aconf->status & CONF_OPS));
 
-  if (oper_password_match(password, aconf->passwd)) {
-    unsigned int old_mode = (cli_flags(sptr) & ALL_UMODES);
+  if (oper_password_match(password, aconf->passwd))
+  {
+    struct Flags old_mode = cli_flags(sptr);
 
     if (ACR_OK != attach_conf(sptr, aconf)) {
       send_reply(sptr, ERR_NOOPERHOST);
@@ -175,13 +177,14 @@ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     }
     cli_handler(cptr) = OPER_HANDLER;
 
+    SetFlag(sptr, FLAG_WALLOP);
+    SetFlag(sptr, FLAG_SERVNOTICE);
+    SetFlag(sptr, FLAG_DEBUG);
     
-    cli_flags(sptr) |= (FLAGS_WALLOP | FLAGS_SERVNOTICE | FLAGS_DEBUG);
-
     set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD);
     client_set_privs(sptr, aconf);
     cli_max_sendq(sptr) = 0; /* Get the sendq from the oper's class */
-    send_umode_out(cptr, sptr, old_mode, HasPriv(sptr, PRIV_PROPAGATE));
+    send_umode_out(cptr, sptr, &old_mode, HasPriv(sptr, PRIV_PROPAGATE));
     send_reply(sptr, RPL_YOUREOPER);
 
     sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) is now operator (%c)",
@@ -190,7 +193,8 @@ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 
     log_write(LS_OPER, L_INFO, 0, "OPER (%s) by (%#C)", name, sptr);
   }
-  else {
+  else
+  {
     send_reply(sptr, ERR_PASSWDMISMATCH);
     sendto_opmask_butone(0, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s)",
                         parv[0], cli_user(sptr)->username, cli_sockhost(sptr));
@@ -208,9 +212,10 @@ int ms_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   /*
    * if message arrived from server, trust it, and set to oper
    */
-  if (!IsServer(sptr) && !IsOper(sptr)) {
+  if (!IsServer(sptr) && !IsOper(sptr))
+  {
     ++UserStats.opers;
-    cli_flags(sptr) |= FLAGS_OPER;
+    SetFlag(sptr, FLAG_OPER);
     sendcmdto_serv_butone(sptr, CMD_MODE, cptr, "%s :+o", parv[0]);
   }
   return 0;
index ddfd734955d1fa648ce9216af3021b6d97daf775..aab68f51d22e7a1e0379a8612cb822a1637d7e51 100644 (file)
@@ -138,6 +138,8 @@ int mo_opmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   struct Channel *chptr = 0;
   struct ModeBuf mbuf;
+  char *chname, *qreason;
+  int force = 0;
   struct Membership *member;
 
   if (!feature_bool(FEAT_CONFIG_OPERCMDS))
@@ -146,14 +148,22 @@ int mo_opmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   if (parc < 3)
     return need_more_params(sptr, "OPMODE");
 
-  clean_channelname(parv[1]);
+  chname = parv[1];
+  if (*chname == '!')
+  {
+    chname++;
+    if (!HasPriv(sptr, IsLocalChannel(chname) ? PRIV_FORCE_LOCAL_OPMODE : PRIV_FORCE_OPMODE))
+      return send_reply(sptr, ERR_NOPRIVILEGES);
+    force = 1;
+  }
+  clean_channelname(chname);
 
   if (!HasPriv(sptr,
-              IsLocalChannel(parv[1]) ? PRIV_LOCAL_OPMODE : PRIV_OPMODE))
+              IsLocalChannel(chname) ? PRIV_LOCAL_OPMODE : PRIV_OPMODE))
     return send_reply(sptr, ERR_NOPRIVILEGES);
 
-  if (('#' != *parv[1] && '&' != *parv[1]) || !(chptr = FindChannel(parv[1])))
-    return send_reply(sptr, ERR_NOSUCHCHANNEL, parv[1]);
+  if (!IsChannelName(chname) || !(chptr = FindChannel(chname)))
+    return send_reply(sptr, ERR_NOSUCHCHANNEL, chname);
 
   if (!(member = find_member_link(chptr, sptr)))
     return send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
index 020b97a0bf0ba32db759a711c44b2bd1692a0412..492469202f0e9a0e0987a95c58447e3c5827abb6 100644 (file)
@@ -110,7 +110,7 @@ int m_part(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   char *p = 0;
   char *name;
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   /* check number of arguments */
   if (parc < 2 || parv[1][0] == '\0')
@@ -168,7 +168,7 @@ int ms_part(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   char *p = 0;
   char *name;
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   /* check number of arguments */
   if (parc < 2 || parv[1][0] == '\0')
@@ -194,6 +194,14 @@ int ms_part(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     if (IsZombie(member)) /* figure out special flags... */
       flags |= CHFL_ZOMBIE;
 
+    /*
+     * XXX BUG: If a client /part's with a part notice, on channels where
+     * he's banned, local clients will not see the part notice, but remote
+     * clients will.
+     */
+    if (!member_can_send_to_channel(member))
+      flags |= CHFL_BANNED;
+
     /* part user from channel */
     joinbuf_join(&parts, chptr, flags);
   }
index 82c493b9e968ce49b0564b131d76eefcd856103f..435b7c68d1006b89ef0f1674c9390946832b6f82 100644 (file)
 #include "msg.h"
 #include "numeric.h"
 #include "numnicks.h"
+#include "opercmds.h"
 #include "s_debug.h"
 #include "send.h"
 
 #include <assert.h>
+#include <stdlib.h>
 #include <string.h>
 
 /*
@@ -175,15 +177,24 @@ int m_ping(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 int mo_ping(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   struct Client* acptr;
-  char*          destination;
+  char *destination, *origin;
   assert(0 != cptr);
   assert(cptr == sptr);
 
   if (parc < 2 || EmptyString(parv[1]))
     return send_reply(sptr, ERR_NOORIGIN);
 
+  origin = parv[1];
   destination = parv[2];        /* Will get NULL or pointer (parc >= 2!!) */
 
+  if (parc > 3)
+  {
+    /* AsLL ping, send reply back */
+    int diff = atoi(militime_float(parv[3]));
+    sendcmdto_one(&me, CMD_PONG, sptr, "%C %s %s %i %s", &me, origin,
+                  parv[3], diff, militime_float(NULL));
+    return 0;
+  }
   if (!EmptyString(destination) && 0 != ircd_strcmp(destination, cli_name(&me))) {
     if ((acptr = FindServer(destination)))
       sendcmdto_one(sptr, CMD_PING, acptr, "%C :%s", sptr, destination);
index 74b4fcb0258125f6e541b91d90e08dfd5d069b59..a1ecc210ba109f4386241177d3855486d014b5e2 100644 (file)
@@ -89,6 +89,7 @@
 #include "msg.h"
 #include "numeric.h"
 #include "numnicks.h"
+#include "opercmds.h"
 #include "s_user.h"
 #include "send.h"
 
@@ -116,15 +117,32 @@ int ms_pong(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   }
   origin      = parv[1];
   destination = parv[2];
-  cli_flags(cptr) &= ~FLAGS_PINGSENT;
-  cli_flags(sptr) &= ~FLAGS_PINGSENT;
+  ClrFlag(cptr, FLAG_PINGSENT);
+  ClrFlag(sptr, FLAG_PINGSENT);
   cli_lasttime(cptr) = CurrentTime;
 
-  if (!EmptyString(destination) && 0 != ircd_strcmp(destination, cli_name(&me))) {
+  if (parc > 5)
+  {
+    /* AsLL pong */
+    cli_serv(cptr)->asll_rtt = atoi(militime_float(parv[3]));
+    cli_serv(cptr)->asll_to = atoi(parv[4]);
+    cli_serv(cptr)->asll_from = atoi(militime_float(parv[5]));
+    return 0;
+  }
+  
+  if (EmptyString(destination))
+    return 0;
+  
+  if (*destination == '!')
+  {
+    /* AsLL ping reply from a non-AsLL server */
+    cli_serv(cptr)->asll_rtt = atoi(militime_float(destination + 1));
+  }
+  else if (0 != ircd_strcmp(destination, cli_name(&me)))
+  {
     struct Client* acptr;
-    if ((acptr = FindClient(destination))) {
+    if ((acptr = FindClient(destination)))
       sendcmdto_one(sptr, CMD_PONG, acptr, "%s %s", origin, destination);
-    }
   }
   return 0;
 }
@@ -142,7 +160,7 @@ int mr_pong(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   assert(cptr == sptr);
   assert(!IsRegistered(sptr));
 
-  cli_flags(cptr) &= ~FLAGS_PINGSENT;
+  ClrFlag(cptr, FLAG_PINGSENT);
   cli_lasttime(cptr) = CurrentTime;
   /*
    * Check to see if this is a PONG :cookie reply from an
@@ -175,7 +193,7 @@ int m_pong(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   assert(0 != cptr);
   assert(cptr == sptr);
-  cli_flags(cptr) &= ~FLAGS_PINGSENT;
+  ClrFlag(cptr, FLAG_PINGSENT);
   cli_lasttime(cptr) = CurrentTime;
   return 0;
 }
index aee3c857ca9e39c75bc05c2f2c41fdcd8016e584..1d257e31c13321e7e3158388d2d134dfb1971f03 100644 (file)
@@ -111,7 +111,7 @@ int m_privmsg(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   assert(cptr == sptr);
   assert(0 != cli_user(sptr));
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   if (feature_bool(FEAT_IDLE_FROM_MSG))
     cli_user(sptr)->last = CurrentTime;
@@ -152,7 +152,7 @@ int ms_privmsg(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   char* name;
   char* server;
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   if (parc < 3) {
     /*
@@ -201,7 +201,7 @@ int mo_privmsg(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   assert(cptr == sptr);
   assert(0 != cli_user(sptr));
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(cptr, FLAG_TS8);
 
   if (feature_bool(FEAT_IDLE_FROM_MSG))
     cli_user(sptr)->last = CurrentTime;
index c426132930b5ded5444fcf6f8e06fd865f9abf73..3dafded80a7809d05160360c90fa9f25b2c0bb21 100644 (file)
@@ -85,7 +85,6 @@
 #include "hash.h"
 #include "ircd.h"
 #include "ircd_log.h"
-#include "ircd_policy.h"
 #include "ircd_features.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "s_serv.h"
 #include "send.h"
 #include "userload.h"
-#include "map.h"
 
 #include <assert.h>
 #include <stdlib.h>
index ad6ac3c13757fadf4f11b295d93e88c751b24b1a..6240b52c1f8c151cbe4672cd70fa99245be78602 100644 (file)
  *
  * parv[0] = sender prefix
  * parv[1] = new time
- * parv[2] = servername (Only used when sptr is an Oper).
+ * parv[2] = server name (Only used when sptr is an Oper).
  */
 int ms_settime(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   time_t t;
-  long int dt;
+  long dt;
   static char tbuf[11];
   struct DLink *lp;
 
-  if (!IsPrivileged(sptr))
-    return 0;
-
   if (parc < 2)
     return need_more_params(sptr, "SETTIME");
 
-  if (parc == 2 && MyUser(sptr))
-    parv[parc++] = cli_name(&me);
-
   t = atoi(parv[1]);
   dt = TStime() - t;
 
   if (t < OLDEST_TS || dt < -9000000)
   {
-    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :SETTIME: Bad value", sptr);
+    if (IsServer(sptr))
+      protocol_violation(sptr, "SETTIME: Bad value (%Tu, delta %l)", t, dt);
+    else
+      sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :SETTIME: Bad value (%Tu, "
+                    "delta %l)", sptr, t, dt);
+      sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :SETTIME: Bad value", sptr);
     return 0;
   }
 
-  if (IsServer(sptr))           /* send to unlagged servers */
+  /* reset time... */
+  if (feature_bool(FEAT_RELIABLE_CLOCK))
   {
-    if (feature_bool(FEAT_RELIABLE_CLOCK)) {
-      ircd_snprintf(0, tbuf, sizeof(tbuf), "%Tu", TStime());
-      parv[1] = tbuf;
-    }
+    ircd_snprintf(0, tbuf, sizeof(tbuf), "%Tu", TStime());
+    parv[1] = tbuf;
+  }
 
+  if (BadPtr(parv[2]))
+  {
     for (lp = cli_serv(&me)->down; lp; lp = lp->next)
-      if (cptr != lp->value.cptr && MsgQLength(&(cli_sendQ(lp->value.cptr))) < 8000)
-       sendcmdto_one(sptr, CMD_NOTICE, lp->value.cptr, "%s", parv[1]);
+      if (cptr != lp->value.cptr)
+        sendcmdto_prio_one(sptr, CMD_SETTIME, lp->value.cptr, "%s", parv[1]);
   }
   else
   {
-    ircd_snprintf(0, tbuf, sizeof(tbuf), "%Tu", TStime());
-    parv[1] = tbuf;
     if (hunt_server_prio_cmd(sptr, CMD_SETTIME, cptr, 1, "%s %C", 2, parc,
-                            parv) != HUNTED_ISME)
+                             parv) != HUNTED_ISME)
+    {
+      /* If the destination was *not* me, but I'm RELIABLE_CLOCK and the
+       * delta is more than 30 seconds off, bounce back a corrected
+       * SETTIME
+       */
+      if (feature_bool(FEAT_RELIABLE_CLOCK) && (dt > 30 || dt < -30))
+        sendcmdto_prio_one(&me, CMD_SETTIME, cptr, "%s %C", parv[1], cptr);
       return 0;
+    }
   }
 
-  if (feature_bool(FEAT_RELIABLE_CLOCK)) {
+  if (feature_bool(FEAT_RELIABLE_CLOCK))
+  {
+    /* don't apply settime--reliable */
     if ((dt > 600) || (dt < -600))
-      sendcmdto_serv_butone(&me, CMD_WALLOPS, 0, ":Bad SETTIME from %s: %Tu",
-                           cli_name(sptr), t);
-    if (IsUser(sptr)) {
+      sendcmdto_serv_butone(&me, CMD_DESYNCH, 0, ":Bad SETTIME from %s: %Tu "
+                            "(delta %l)", cli_name(sptr), t, dt);
+    /* Let user know we're ignoring him */
+    if (IsUser(sptr))
+    {
       sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :clock is not set %ld "
                    "seconds %s : RELIABLE_CLOCK is defined", sptr,
                    (dt < 0) ? -dt : dt, (dt < 0) ? "forwards" : "backwards");
     }
-  } else {
+  }
+  else
+  {
     sendto_opmask_butone(0, SNO_OLDSNO, "SETTIME from %s, clock is set %ld "
                         "seconds %s", cli_name(sptr), (dt < 0) ? -dt : dt,
                         (dt < 0) ? "forwards" : "backwards");
+    /* Apply time change... */
     TSoffset -= dt;
-    if (IsUser(sptr)) {
+    /* Let the issuing user know what we did... */
+    if (IsUser(sptr))
+    {
       sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :clock is set %ld seconds %s",
-                   sptr, (dt < 0) ? -dt : dt,
-                   (dt < 0) ? "forwards" : "backwards");
+                    sptr, (dt < 0) ? -dt : dt,
+                    (dt < 0) ? "forwards" : "backwards");
     }
   }
 
@@ -185,12 +201,12 @@ int ms_settime(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 int mo_settime(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   time_t t;
-  long int dt;
+  long dt;
   static char tbuf[11];
-  struct DLink *lp;
 
-  if (!IsPrivileged(sptr))
-    return 0;
+  /* Must be a global oper */
+  if (!IsOper(sptr))
+    return send_reply(sptr, ERR_NOPRIVILEGES);
 
   if (parc < 2)
     return need_more_params(sptr, "SETTIME");
@@ -199,6 +215,14 @@ int mo_settime(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     parv[parc++] = cli_name(&me);
 
   t = atoi(parv[1]);
+  /* If we're reliable_clock or if the oper specified a 0 time, use current */
+  if (!t || feature_bool(FEAT_RELIABLE_CLOCK))
+  {
+    t = TStime();
+    ircd_snprintf(0, tbuf, sizeof(tbuf), "%Tu", TStime());
+    parv[1] = tbuf;
+  }
+
   dt = TStime() - t;
 
   if (t < OLDEST_TS || dt < -9000000)
@@ -207,45 +231,30 @@ int mo_settime(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     return 0;
   }
 
-  if (IsServer(sptr))           /* send to unlagged servers */
-  {
-    if (feature_bool(FEAT_RELIABLE_CLOCK)) {
-      ircd_snprintf(0, tbuf, sizeof(tbuf), "%Tu", TStime());
-      parv[1] = tbuf;
-    }
+  if (hunt_server_prio_cmd(sptr, CMD_SETTIME, cptr, 1, "%s %C", 2, parc,
+                           parv) != HUNTED_ISME)
+    return 0;
 
-    for (lp = cli_serv(&me)->down; lp; lp = lp->next)
-      if (cptr != lp->value.cptr && MsgQLength(&(cli_sendQ(lp->value.cptr))) < 8000)
-       sendcmdto_prio_one(sptr, CMD_SETTIME, lp->value.cptr, "%s", parv[1]);
+  if (feature_bool(FEAT_RELIABLE_CLOCK))
+  {
+    if ((dt > 600) || (dt < -600))
+      sendcmdto_serv_butone(&me, CMD_DESYNCH, 0, ":Bad SETTIME from %s: %Tu "
+                            "(delta %l)", cli_name(sptr), t, dt);
+    if (IsUser(sptr))
+      sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :clock is not set %ld seconds "
+                    "%s: RELIABLE_CLOCK is defined", sptr, (dt < 0) ? -dt : dt,
+                    (dt < 0) ? "forward" : "backward");
   }
   else
   {
-    ircd_snprintf(0, tbuf, sizeof(tbuf), "%Tu", TStime());
-    parv[1] = tbuf;
-    if (hunt_server_prio_cmd(sptr, CMD_SETTIME, cptr, 1, "%s %C", 2, parc,
-                            parv) != HUNTED_ISME)
-      return 0;
-  }
-
-  if (feature_bool(FEAT_RELIABLE_CLOCK)) {
-    if ((dt > 600) || (dt < -600))
-      sendcmdto_serv_butone(&me, CMD_WALLOPS, 0, ":Bad SETTIME from %s: %Tu",
-                           cli_name(sptr), t);
-    if (IsUser(sptr)) {
-      sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :clock is not set %ld "
-                   "seconds %s : RELIABLE_CLOCK is defined", sptr,
-                   (dt < 0) ? -dt : dt, (dt < 0) ? "forwards" : "backwards");
-    }
-  } else {
     sendto_opmask_butone(0, SNO_OLDSNO, "SETTIME from %s, clock is set %ld "
                         "seconds %s", cli_name(sptr), (dt < 0) ? -dt : dt,
                         (dt < 0) ? "forwards" : "backwards");
     TSoffset -= dt;
-    if (IsUser(sptr)) {
+    if (IsUser(sptr))
       sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :clock is set %ld seconds %s",
                    sptr, (dt < 0) ? -dt : dt,
                    (dt < 0) ? "forwards" : "backwards");
-    }
   }
 
   return 0;
index b71d28e1b7d61aa2a7809d1caaa431880634b5b7..8611b21da67ff5aa403be095363d18e4a6ff34d4 100644 (file)
@@ -60,7 +60,7 @@ int ms_squit(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   const char* server = parv[1];
   struct Client *acptr;
-  time_t timestamp;
+  time_t timestamp = 0;
   char *comment = 0;
   
   if (parc < 2) 
@@ -84,19 +84,22 @@ int ms_squit(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   }
   
   /* If they are squitting me, we reverse it */
-  if (IsMe(acptr)) {
+  if (IsMe(acptr))
     acptr = cptr; /* Bugfix by Prefect */
-  }
-       
-  timestamp = atoi(parv[2]);
+
+  if (parc > 2)
+    timestamp = atoi(parv[2]);
+  else
+    protocol_violation(cptr, "SQUIT with no timestamp/reason");
 
   /* If atoi(parv[2]) == 0 we must indeed squit !
    * It will be our neighbour.
    */
-  if ( timestamp != 0 && timestamp != cli_serv(acptr)->timestamp) {
+  if ( timestamp != 0 && timestamp != cli_serv(acptr)->timestamp)
+  {
     protocol_violation(sptr, "Issued SQUIT for %C with wrong timestamp %Tu "
-                      "(%Tu) (ignored)", acptr, timestamp,
-                      cli_serv(acptr)->timestamp);
+                       "(%Tu) (ignored)", acptr, timestamp,
+                       cli_serv(acptr)->timestamp);
     Debug((DEBUG_NOTICE, "Ignoring SQUIT with the wrong timestamp"));
     return 0;
   }
index 8bb8e67e8a9cbf05749c5077a796cd069dac2d68..aeb99958e8600ecd2542d365037eb87adbcbc741 100644 (file)
  */
 #include "config.h"
 
-#include "handlers.h"
-/*
- * XXX - ack!!!
- */
-#include "s_stats.h"
-#include "channel.h"
-#include "class.h"
 #include "client.h"
-#include "gline.h"
-#include "hash.h"
 #include "ircd.h"
-#include "ircd_alloc.h"
-#include "ircd_chattr.h"
-#include "ircd_events.h"
 #include "ircd_features.h"
-#include "ircd_policy.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
-#include "list.h"
-#include "listener.h"
-#include "match.h"
-#include "motd.h"
 #include "msg.h"
 #include "numeric.h"
-#include "numnicks.h"
-#include "opercmds.h"
-#include "s_bsd.h"
-#include "s_conf.h"
-#include "s_debug.h"
-#include "s_misc.h"
-#include "s_serv.h"
+#include "s_stats.h"
 #include "s_user.h"
 #include "send.h"
 #include "struct.h"
-#include "userload.h"
 
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
-
-int report_klines(struct Client* sptr, char* mask, int limit_query)
-{
-  int   wilds = 0;
-  int   count = 3;
-  char* user  = 0;
-  char* host;
-  const struct DenyConf* conf;
-
-  if (EmptyString(mask)) {
-    if (limit_query)
-      return need_more_params(sptr, "STATS K");
-    else
-      report_deny_list(sptr);
-    return 1;
-  }
-
-  if (!limit_query) {
-    wilds = string_has_wildcards(mask);
-    count = 1000;
-  }
-
-  if ((host = strchr(mask, '@'))) {
-    user = mask;
-    *host++ = '\0';
-  }
-  else {
-    host = mask;
-  }
-
-  for (conf = conf_get_deny_list(); conf; conf = conf->next) {
-    if ((!wilds && ((user || conf->hostmask) &&
-       !match(conf->hostmask, host) &&
-       (!user || !match(conf->usermask, user)))) ||
-       (wilds && !mmatch(host, conf->hostmask) &&
-       (!user || !mmatch(user, conf->usermask))))
-    {
-      send_reply(sptr, RPL_STATSKLINE,
-                (conf->flags & DENY_FLAGS_IP) ? 'k' : 'K',
-                 conf->hostmask, conf->message, conf->usermask);
-      if (--count == 0)
-       return 1;
-    }
-  }
-  /* send_reply(sptr, RPL_ENDOFSTATS, stat); */
-  return 1;
-}
-
-static int report_servers_verbose(struct Client *sptr, char stat)
-{
-  struct Client *acptr;
-
-  /* lowercase 'v' is for human-readable,
-   * uppercase 'V' is for machine-readable */
-  if (stat == 'v')
-    send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE,
-              "%-20s %-20s Burst Hops Numeric   Lag Clients/Max Proto "
-              "%-10s :Info", "Servername", "Uplink", "LinkTS");
-
-  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr))
-  {
-    if (!IsServer(acptr) && !IsMe(acptr))
-      continue;
-    send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE, stat == 'v' ?
-              "%-20s %-20s %c%c    %4i %s %-4i %5i %5i %5i P%-2i   %Tu :%s" :
-              "%s %s %c%c %i %s %i %i %i %i P%i %Tu :%s",
-              cli_name(acptr),
-              cli_name(cli_serv(acptr)->up),
-              IsBurst(acptr) ? 'B' : '-',
-              IsBurstAck(acptr) ? 'A' : '-',
-              cli_hopcount(acptr),
-              NumServ(acptr),
-              base64toint(cli_yxx(acptr)),
-              cli_serv(acptr)->lag,
-              cli_serv(acptr)->clients,
-              cli_serv(acptr)->nn_mask,
-              cli_serv(acptr)->prot,
-              cli_serv(acptr)->timestamp,
-              cli_info(acptr));
-  }
-
-  return 0;
-}
-
-
 /*
  * m_stats - generic message handler
  *
  *    parv[0] = sender prefix
- *    parv[1] = statistics selector (defaults to Message frequency)
+ *    parv[1] = statistics selector
  *    parv[2] = target server (current server defaulted, if omitted)
  * And 'stats l' and 'stats' L:
- *    parv[3] = server mask ("*" defaulted, if omitted)
+ *    parv[3] = server mask ("*" default, if omitted)
  * Or for stats p,P:
  *    parv[3] = port mask (returns p-lines when its port is matched by this)
  * Or for stats k,K,i and I:
- *    parv[3] = [user@]host.name  (returns which K/I-lines match this)
- *           or [user@]host.mask  (returns which K/I-lines are mmatched by this)
- *              (defaults to old reply if ommitted, when local or Oper)
+ *    parv[3] = [user@]host.name (returns which K/I-lines match this)
+ *           or [user@]host.mask (returns which K/I-lines are mmatched by this)
+ *              (defaults to old reply if omitted, when local or Oper)
  *              A remote mask (something containing wildcards) is only
  *              allowed for IRC Operators.
- * Or for stats M:
- *    parv[3] = time param
- *    parv[4] = time param 
- *    (see report_memleak_stats() in runmalloc.c for details)
- *
- * This function is getting really ugly. -Ghostwolf
  */
-int m_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
+int
+m_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
-  char stat = parc > 1 ? parv[1][0] : '\0';
-  const char **infotext = statsinfo;
-
-  if (hunt_stats(cptr, sptr, parc, parv, stat, HEAD_IN_SAND_REMOTE)
-      != HUNTED_ISME)
-    return 0;
-
-  switch (stat)
-  {
-    case 'L':
-    case 'l':
-#ifdef HEAD_IN_SAND_STATS_L
-       return m_not_oper(sptr,cptr,parc,parv);
-#else
-    {
-      struct Client *acptr;
-      int i;
-      int doall = 0;
-      int wilds = 0;
-      char *name = "*";
-
-      if (parc > 3 && !EmptyString(parv[3])) {
-        name = parv[3];
-        wilds = string_has_wildcards(name);
-      }
-      else
-        doall = 1;
-      /*
-       * Send info about connections which match, or all if the
-       * mask matches me.name.  Only restrictions are on those who
-       * are invisible not being visible to 'foreigners' who use
-       * a wild card based search to list it.
-       */
-      send_reply(sptr, SND_EXPLICIT | RPL_STATSLINKINFO, "Connection SendQ "
-                 "SendM SendKBytes RcveM RcveKBytes :Open since");
-      for (i = 0; i <= HighestFd; i++)
-      {
-        if (!(acptr = LocalClientArray[i]))
-          continue;
-        /* Don't return clients when this is a request for `all' */
-        if (doall && IsUser(acptr))
-          continue;
-        /* Don't show invisible people to non opers unless they know the nick */
-        if (IsInvisible(acptr) && (doall || wilds) && !IsAnOper(acptr) && (acptr != sptr))
-          continue;
-        /* Only show the ones that match the given mask - if any */
-        if (!doall && wilds && match(name, cli_name(acptr)))
-          continue;
-        /* Skip all that do not match the specific query */
-        if (!(doall || wilds) && 0 != ircd_strcmp(name, cli_name(acptr)))
-          continue;
-        send_reply(sptr, SND_EXPLICIT | RPL_STATSLINKINFO,
-                   "%s %u %u %u %u %u :%Tu", (*(cli_name(acptr))) ? cli_name(acptr) : "<unregistered>",
-                   (int)MsgQLength(&(cli_sendQ(acptr))), (int)cli_sendM(acptr),
-                   (int)cli_sendK(acptr), (int)cli_receiveM(acptr),
-                   (int)cli_receiveK(acptr), CurrentTime - cli_firsttime(acptr));
-      }
-    }
-#endif
-      break;
-
-    case 'C':
-    case 'c':
-#ifdef HEAD_IN_SAND_STATS_C
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      report_configured_links(sptr, CONF_SERVER);
-#endif
-      break;
-
-    case 'E':
-    case 'e': /* report engine name */
-#ifdef HEAD_IN_SAND_STATS_E
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      send_reply(sptr, RPL_STATSENGINE, engine_name());
-#endif
-      break;
-
-    case 'G':
-    case 'g': /* send glines */
-#ifdef HEAD_IN_SAND_STATS_G
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      gline_stats(sptr);
-#endif
-      break;
-
-    case 'H':
-    case 'h':
-#ifdef HEAD_IN_SAND_STATS_H
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      report_configured_links(sptr, CONF_HUB | CONF_LEAF);
-#endif
-      break;
-
-    case 'K':
-    case 'k':    /* display CONF_IPKILL as well as CONF_KILL -Kev */
-#ifdef HEAD_IN_SAND_STATS_K
-    /* Simple version - if you want to fix it - send in a patch */
-    return m_not_oper(sptr,cptr,parc,parv);
-#else
-      if (0 == report_klines(sptr, (parc == 4) ? parv[3] : 0, 0))
-        return 0;
-#endif
-      break;
-    case 'F':
-    case 'f':
-#ifdef HEAD_IN_SAND_STATS_F
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      feature_report(sptr);
-#endif
-      break;
-
-    case 'I':
-    case 'i':
-#ifdef HEAD_IN_SAND_STATS_I
-    /* Simple version - if you want to fix it - send in a patch */
-    return m_not_oper(sptr,cptr,parc,parv);
-#else
-    {
-      struct ConfItem *aconf;
-      int wilds = 0;
-      int count = 1000;
-      char* host;
-
-      if (parc < 4) {
-        report_configured_links(sptr, CONF_CLIENT);
-        break;
-      }
-      if (EmptyString(parv[3]))
-        return need_more_params(sptr, "STATS I");
-
-      host = parv[3];
-      wilds = string_has_wildcards(host);
-
-      for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
-       if (CONF_CLIENT == aconf->status) {
-         if ((!wilds && (!match(aconf->host, host) ||
-             !match(aconf->name, host))) ||
-             (wilds && (!mmatch(host, aconf->host) ||
-             !mmatch(host, aconf->name))))
-         {
-           if (aconf->passwd && IsDigit(*aconf->passwd) && 
-               (!aconf->passwd[1] || 
-                (IsDigit(aconf->passwd[1]) && !aconf->passwd[2])))
-             send_reply(sptr, RPL_STATSILINE, 'I', aconf->host, aconf->passwd, 
-                       aconf->name, aconf->port, get_conf_class(aconf));
-           else 
-             send_reply(sptr, RPL_STATSILINE, 'I', aconf->host, "*",
-                        aconf->name, aconf->port, get_conf_class(aconf));
-           
-           if (--count == 0)
-             break;
-         }
-       }
-      }
-    }
-#endif
-      break;
-
-    case 'M':
-#ifdef HEAD_IN_SAND_STATS_M
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-#if defined(MDEBUG)
-      send_reply(sptr, RPL_STATMEMTOT, fda_get_byte_count(),
-                 fda_get_block_count());
-#endif
-#endif
-      break;
-
-    case 'm':
-#ifdef HEAD_IN_SAND_STATS_m
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-    {
-      struct Message *mptr;
-
-      for (mptr = msgtab; mptr->cmd; mptr++)
-        if (mptr->count)
-          send_reply(sptr, RPL_STATSCOMMANDS, mptr->cmd, mptr->count,
-                     mptr->bytes);
-    }
-#endif
-      break;
-
-    case 'o':
-    case 'O':
-#ifdef HEAD_IN_SAND_STATS_O
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      report_configured_links(sptr, CONF_OPS);
-#endif
-      break;
-
-    case 'p':
-    case 'P':
-      /*
-       * show listener ports
-       * show hidden ports to opers, if there are more than 3 parameters,
-       * interpret the fourth parameter as the port number.
-       */ 
-#ifdef HEAD_IN_SAND_STATS_P
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      show_ports(sptr, 0, (parc > 3) ? atoi(parv[3]) : 0, 100);
-#endif
-      break;
-
-    case 'R':
-    case 'r':
-#ifdef HEAD_IN_SAND_STATS_R
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-#ifdef DEBUGMODE
-      send_usage(sptr, parv[0]);
-#endif
-#endif
-      break;
-
-    case 'D':
-#ifdef HEAD_IN_SAND_STATS_D
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      report_crule_list(sptr, CRULE_ALL);
-#endif
-      break;
-
-    case 'd':
-#ifdef HEAD_IN_SAND_STATS_d
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      report_crule_list(sptr, CRULE_MASK);
-#endif
-      break;
-
-    case 't':
-#ifdef HEAD_IN_SAND_STATS_t
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      tstats(sptr, parv[0]);
-#endif
-      break;
-
-    case 'T':
-#ifdef HEAD_IN_SAND_STATS_T
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      motd_report(sptr);
-#endif
-      break;
-
-    case 'U':
-#ifdef HEAD_IN_SAND_STATS_U
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      report_configured_links(sptr, CONF_UWORLD);
-#endif
-      break;
-
-    case 'u':
-#ifdef HEAD_IN_SAND_STATS_u
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-    {
-      time_t nowr;
-
-      nowr = CurrentTime - cli_since(&me);
-      send_reply(sptr, RPL_STATSUPTIME, nowr / 86400, (nowr / 3600) % 24,
-                 (nowr / 60) % 60, nowr % 60);
-      send_reply(sptr, RPL_STATSCONN, max_connection_count, max_client_count);
-    }
-#endif
-      break;
-
-    case 'W':
-    case 'w':
-#ifdef HEAD_IN_SAND_STATS_W
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      calc_load(sptr);
-#endif
-      break;
-
-    case 'X':
-    case 'x':
-#ifdef HEAD_IN_SAND_STATS_X
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-#ifdef  DEBUGMODE
-      class_send_meminfo(sptr);
-      send_listinfo(sptr, parv[0]);
-#endif
-#endif
-      break;
-
-    case 'Y':
-    case 'y':
-#ifdef HEAD_IN_SAND_STATS_Y
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      report_classes(sptr);
-#endif
-      break;
-
-    case 'Z':
-    case 'z':
-#ifdef HEAD_IN_SAND_STATS_Z
-      return m_not_oper(sptr,cptr,parc,parv);
-#else
-      count_memory(sptr, parv[0]);
-#endif
-      break;
-
-    default:
-      stat = '*';
-      while (*infotext)
-        sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s", sptr, *infotext++);
-      break;
+  unsigned char stat = parc > 1 ? parv[1][0] : '\0';
+  struct StatDesc *sd;
+  char *param = 0;
+
+  /* If we didn't find a descriptor and this is my client, send them help */
+  if (!(sd = statsmap[(int)stat])) {
+    stat = '*';
+    sd = statsmap[(int)stat];
   }
-  send_reply(sptr, RPL_ENDOFSTATS, stat);
-  return 0;
-}
 
-/*
- * ms_stats - server message handler
- *
- *    parv[0] = sender prefix
- *    parv[1] = statistics selector (defaults to Message frequency)
- *    parv[2] = target server (current server defaulted, if omitted)
- * And 'stats l' and 'stats' L:
- *    parv[3] = server mask ("*" defaulted, if omitted)
- * Or for stats p,P:
- *    parv[3] = port mask (returns p-lines when its port is matched by this)
- * Or for stats k,K,i and I:
- *    parv[3] = [user@]host.name  (returns which K/I-lines match this)
- *           or [user@]host.mask  (returns which K/I-lines are mmatched by this)
- *              (defaults to old reply if ommitted, when local or Oper)
- *              A remote mask (something containing wildcards) is only
- *              allowed for IRC Operators.
- * Or for stats M:
- *    parv[3] = time param
- *    parv[4] = time param 
- *    (see report_memleak_stats() in runmalloc.c for details)
- *
- * This function is getting really ugly. -Ghostwolf
- */
-int ms_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
-{
-  struct Message *mptr;
-  struct Client *acptr;
-  struct ConfItem *aconf;
-  char stat = parc > 1 ? parv[1][0] : '\0';
-  int i;
-
-  if (hunt_stats(cptr, sptr, parc, parv, stat, 0) != HUNTED_ISME)
-    return 0;
-
-  switch (stat)
-  {
-    case 'L':
-    case 'l':
-    {
-      int doall = 0;
-      int wilds = 0;
-      char *name = "*";
+  assert(sd != 0);
 
-      if (parc > 3 && !EmptyString(parv[3])) {
-        name = parv[3];
-        wilds = string_has_wildcards(name);
-      }
-      else
-        doall = 1;
-      /*
-       * Send info about connections which match, or all if the
-       * mask matches me.name.  Only restrictions are on those who
-       * are invisible not being visible to 'foreigners' who use
-       * a wild card based search to list it.
-       */
-      send_reply(sptr, SND_EXPLICIT | RPL_STATSLINKINFO, "Connection SendQ "
-                 "SendM SendKBytes RcveM RcveKBytes :Open since");
-      for (i = 0; i <= HighestFd; i++)
-      {
-        if (!(acptr = LocalClientArray[i]))
-          continue;
-        /* Don't return clients when this is a request for `all' */
-        if (doall && IsUser(acptr))
-          continue;
-        /* Don't show invisible people to unauthorized people when using
-         * wildcards  -- Is this still needed now /stats is oper only ? 
-         * Not here, because ms_stats is specifically a remote command, 
-         * thus the check was removed. -Ghostwolf */
-        /* Only show the ones that match the given mask - if any */
-        if (!doall && wilds && match(name, cli_name(acptr)))
-          continue;
-        /* Skip all that do not match the specific query */
-        if (!(doall || wilds) && 0 != ircd_strcmp(name, cli_name(acptr)))
-          continue;
-        send_reply(sptr, SND_EXPLICIT | RPL_STATSLINKINFO,
-                   "%s %u %u %u %u %u :%Tu", cli_name(acptr),
-                   (int)MsgQLength(&(cli_sendQ(acptr))), (int)cli_sendM(acptr),
-                   (int)cli_sendK(acptr), (int)cli_receiveM(acptr),
-                   (int)cli_receiveK(acptr), CurrentTime - cli_firsttime(acptr));
-      }
-      break;
-    }
-    case 'C':
-    case 'c':
-      report_configured_links(sptr, CONF_SERVER);
-      break;
-    case 'E':
-    case 'e': /* report engine name */
-      send_reply(sptr, RPL_STATSENGINE, engine_name());
-      break;
-    case 'G':
-    case 'g': /* send glines */
-      gline_stats(sptr);
-      break;
-    case 'H':
-    case 'h':
-      report_configured_links(sptr, CONF_HUB | CONF_LEAF);
-      break;
-    case 'K':
-    case 'k':    /* display CONF_IPKILL as well as CONF_KILL -Kev */
-      if (0 == report_klines(sptr, (parc > 3) ? parv[3] : 0, !IsOper(sptr)))
-        return 0;
-      break;
-    case 'F':
-    case 'f':
-      feature_report(sptr);
-      break;
-    case 'I':
-    case 'i':
-    {
-      int   wilds = 0;
-      int   count = 3;
-      char* host;
+  /* Check whether the client can issue this command.  If source is
+   * not privileged (server or an operator), then the STAT_FLAG_OPERONLY
+   * flag must not be set, and if the STAT_FLAG_OPERFEAT flag is set,
+   * then the feature given by sd->sd_control must be off.
+   */
+  if (!IsPrivileged(cptr) &&
+      ((sd->sd_flags & STAT_FLAG_OPERONLY) ||
+       ((sd->sd_flags & STAT_FLAG_OPERFEAT) && feature_bool(sd->sd_control))))
+    return send_reply(cptr, ERR_NOPRIVILEGES);
 
-      if (parc < 4 && IsOper(sptr)) {
-        report_configured_links(sptr, CONF_CLIENT);
-        break;
-      }
-      if (parc < 4 || EmptyString(parv[3]))
-        return need_more_params(sptr, "STATS I");
+  /* Check for extra parameter */
+  if ((sd->sd_flags & STAT_FLAG_VARPARAM) && parc > 3 && !EmptyString(parv[3]))
+    param = parv[3];
 
-      if (IsOper(sptr)) {
-        wilds = string_has_wildcards(parv[3]);
-        count = 1000;
-      }
+  /* Ok, track down who's supposed to get this... */
+  if (hunt_server_cmd(sptr, CMD_STATS, cptr, feature_int(FEAT_HIS_REMOTE),
+                     param ? "%s %C :%s" : "%s :%C", 2, parc, parv) !=
+      HUNTED_ISME)
+    return 0; /* Someone else--cool :) */
 
-      host = parv[3];
+  assert(sd->sd_func != 0);
 
-      for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
-       if (CONF_CLIENT == aconf->status) {
-         if ((!wilds && (!match(aconf->host, host) ||
-             !match(aconf->name, host))) ||
-             (wilds && (!mmatch(host, aconf->host) ||
-             !mmatch(host, aconf->name))))
-         {
-           if (aconf->passwd && IsDigit(*aconf->passwd) &&
-               (!aconf->passwd[1] ||
-                (IsDigit(aconf->passwd[1]) && !aconf->passwd[2])))
-             send_reply(sptr, RPL_STATSILINE, 'I', aconf->host,
-                        aconf->passwd, aconf->name, aconf->port,
-                        get_conf_class(aconf));
-              else
-                send_reply(sptr, RPL_STATSILINE, 'I', aconf->host, "*",
-                           aconf->name, aconf->port, get_conf_class(aconf));
+  /* Ok, dispatch the stats function */
+  (*sd->sd_func)(sptr, sd, stat, param);
 
-           if (--count == 0)
-             break;
-         }
-       }
-      }
-      break;
-    }
-    case 'M':
-#if defined(MDEBUG)
-      send_reply(sptr, RPL_STATMEMTOT, fda_get_byte_count(),
-                 fda_get_block_count());
-#endif
-      break;
-    case 'm':
-      for (mptr = msgtab; mptr->cmd; mptr++)
-        if (mptr->count)
-          send_reply(sptr, RPL_STATSCOMMANDS, mptr->cmd, mptr->count,
-                     mptr->bytes);
-      break;
-    case 'o':
-    case 'O':
-      report_configured_links(sptr, CONF_OPS);
-      break;
-    case 'p':
-    case 'P':
-      /*
-       * show listener ports
-       * show hidden ports to opers, if there are more than 3 parameters,
-       * interpret the fourth parameter as the port number, limit non-local
-       * or non-oper results to 8 ports.
-       */ 
-      show_ports(sptr, IsOper(sptr), (parc > 3) ? atoi(parv[3]) : 0, IsOper(sptr) ? 100 : 8);
-      break;
-    case 'R':
-    case 'r':
-#ifdef DEBUGMODE
-      send_usage(sptr, parv[0]);
-#endif
-      break;
-    case 'D':
-      report_crule_list(sptr, CRULE_ALL);
-      break;
-    case 'd':
-      report_crule_list(sptr, CRULE_MASK);
-      break;
-    case 't':
-      tstats(sptr, parv[0]);
-      break;
-    case 'T':
-      motd_report(sptr);
-      break;
-    case 'U':
-      report_configured_links(sptr, CONF_UWORLD);
-      break;
-    case 'u':
-    {
-      time_t nowr;
-
-      nowr = CurrentTime - cli_since(&me);
-      send_reply(sptr, RPL_STATSUPTIME, nowr / 86400, (nowr / 3600) % 24,
-                 (nowr / 60) % 60, nowr % 60);
-      send_reply(sptr, RPL_STATSCONN, max_connection_count, max_client_count);
-      break;
-    }
-    case 'V':
-    case 'v':
-      report_servers_verbose(sptr, stat);
-      break;
-    case 'W':
-    case 'w':
-      calc_load(sptr);
-      break;
-    case 'X':
-    case 'x':
-#ifdef  DEBUGMODE
-      class_send_meminfo(sptr);
-      send_listinfo(sptr, parv[0]);
-#endif
-      break;
-    case 'Y':
-    case 'y':
-      report_classes(sptr);
-      break;
-    case 'Z':
-    case 'z':
-      count_memory(sptr, parv[0]);
-      break;
-    default:
-      stat = '*';
-      break;
-  }
-  send_reply(sptr, RPL_ENDOFSTATS, stat);
-  return 0;
+  /* Done sending them the stats */
+  return send_reply(sptr, RPL_ENDOFSTATS, stat);
 }
-
-/*
- * mo_stats - oper message handler
- *
- *    parv[0] = sender prefix
- *    parv[1] = statistics selector (defaults to Message frequency)
- *    parv[2] = target server (current server defaulted, if omitted)
- * And 'stats l' and 'stats' L:
- *    parv[3] = server mask ("*" defaulted, if omitted)
- * Or for stats p,P:
- *    parv[3] = port mask (returns p-lines when its port is matched by this)
- * Or for stats k,K,i and I:
- *    parv[3] = [user@]host.name  (returns which K/I-lines match this)
- *           or [user@]host.mask  (returns which K/I-lines are mmatched by this)
- *              (defaults to old reply if ommitted, when local or Oper)
- *              A remote mask (something containing wildcards) is only
- *              allowed for IRC Operators.
- * Or for stats M:
- *    parv[3] = time param
- *    parv[4] = time param 
- *    (see report_memleak_stats() in runmalloc.c for details)
- *
- * This function is getting really ugly. -Ghostwolf
- */
-int mo_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
-{
-  struct Message*  mptr;
-  struct Client*   acptr;
-  struct ConfItem* aconf;
-  char             stat = parc > 1 ? parv[1][0] : '\0';
-  const char**     infotext = statsinfo;
-  int              i;
-
-  if (hunt_stats(cptr, sptr, parc, parv, stat, HEAD_IN_SAND_REMOTE)
-      != HUNTED_ISME)
-    return 0;
-
-  switch (stat)
-  {
-    case 'L':
-    case 'l':
-    {
-      int doall = 0, wilds = 0;
-      char* name = "*";
-      if (parc > 3 && !EmptyString(parv[3])) {
-        name = parv[3];
-        wilds = string_has_wildcards(name);
-      }
-      else
-        doall = 1;
-      /*
-       * Send info about connections which match, or all if the
-       * mask matches me.name.  Only restrictions are on those who
-       * are invisible not being visible to 'foreigners' who use
-       * a wild card based search to list it.
-       */
-      send_reply(sptr, SND_EXPLICIT | RPL_STATSLINKINFO, "Connection SendQ "
-                 "SendM SendKBytes RcveM RcveKBytes :Open since");
-      for (i = 0; i <= HighestFd; i++)
-      {
-        if (!(acptr = LocalClientArray[i]))
-          continue;
-        /* Don't return clients when this is a request for `all' */
-        if (doall && IsUser(acptr))
-          continue;
-        /* Only show the ones that match the given mask - if any */
-        if (!doall && wilds && match(name, cli_name(acptr)))
-          continue;
-        /* Skip all that do not match the specific query */
-        if (!(doall || wilds) && 0 != ircd_strcmp(name, cli_name(acptr)))
-          continue;
-        send_reply(sptr, SND_EXPLICIT | RPL_STATSLINKINFO,
-                   "%s %u %u %u %u %u :%Tu", cli_name(acptr),
-                   (int)MsgQLength(&(cli_sendQ(acptr))), (int)cli_sendM(acptr),
-                   (int)cli_sendK(acptr), (int)cli_receiveM(acptr),
-                   (int)cli_receiveK(acptr), CurrentTime - cli_firsttime(acptr));
-      }
-      break;
-    }
-    case 'C':
-    case 'c':
-      report_configured_links(sptr, CONF_SERVER);
-      break;
-    case 'E':
-    case 'e': /* report engine name */
-      send_reply(sptr, RPL_STATSENGINE, engine_name());
-      break;
-    case 'G':
-    case 'g': /* send glines */
-      gline_stats(sptr);
-      break;
-    case 'H':
-    case 'h':
-      report_configured_links(sptr, CONF_HUB | CONF_LEAF);
-      break;
-    case 'K':
-    case 'k':    /* display CONF_IPKILL as well as CONF_KILL -Kev */
-      if (0 == report_klines(sptr, (parc > 3) ? parv[3] : 0, 0))
-        return 0;
-      break;
-    case 'F':
-    case 'f':
-      feature_report(sptr);
-      break;
-    case 'I':
-    case 'i':
-      {
-       int   wilds = 0;
-       int   count = 1000;
-       char* host;
-
-       if (parc < 4) {
-         report_configured_links(sptr, CONF_CLIENT);
-         break;
-       }
-        if (EmptyString(parv[3]))
-          return need_more_params(sptr, "STATS I");
-
-       host = parv[3];
-       wilds = string_has_wildcards(host);
-
-       for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
-         if (CONF_CLIENT == aconf->status) {
-           if ((!wilds && (!match(aconf->host, host) ||
-               !match(aconf->name, host))) ||
-               (wilds && (!mmatch(host, aconf->host) ||
-               !mmatch(host, aconf->name))))
-           {
-             if (aconf->passwd && IsDigit(*aconf->passwd) &&
-                 (!aconf->passwd[1] ||
-                  (IsDigit(aconf->passwd[1]) && !aconf->passwd[2])))
-               send_reply(sptr, RPL_STATSILINE, 'I', aconf->host, 
-                          aconf->passwd, aconf->name, aconf->port, 
-                          get_conf_class(aconf));
-             else 
-               send_reply(sptr, RPL_STATSILINE, 'I', aconf->host, "*",
-                          aconf->name, aconf->port, get_conf_class(aconf));
-
-             if (--count == 0)
-               break;
-           }
-         }
-       }
-      }
-      break;
-    case 'M':
-#if defined(MDEBUG)
-      send_reply(sptr, RPL_STATMEMTOT, fda_get_byte_count(),
-                 fda_get_block_count());
-#endif
-      break;
-    case 'm':
-      for (mptr = msgtab; mptr->cmd; mptr++)
-        if (mptr->count)
-          send_reply(sptr, RPL_STATSCOMMANDS, mptr->cmd, mptr->count,
-                     mptr->bytes);
-      break;
-    case 'o':
-    case 'O':
-      report_configured_links(sptr, CONF_OPS);
-      break;
-    case 'p':
-    case 'P':
-      /*
-       * show listener ports
-       * show hidden ports to opers, if there are more than 3 parameters,
-       * interpret the fourth parameter as the port number, limit non-local
-       * or non-oper results to 8 ports.
-       */ 
-      show_ports(sptr, 1, (parc > 3) ? atoi(parv[3]) : 0, 100);
-      break;
-    case 'R':
-    case 'r':
-#ifdef DEBUGMODE
-      send_usage(sptr, parv[0]);
-#endif
-      break;
-    case 'D':
-      report_crule_list(sptr, CRULE_ALL);
-      break;
-    case 'd':
-      report_crule_list(sptr, CRULE_MASK);
-      break;
-    case 't':
-      tstats(sptr, parv[0]);
-      break;
-    case 'T':
-      motd_report(sptr);
-      break;
-    case 'U':
-      report_configured_links(sptr, CONF_UWORLD);
-      break;
-    case 'u':
-    {
-      time_t nowr;
-
-      nowr = CurrentTime - cli_since(&me);
-      send_reply(sptr, RPL_STATSUPTIME, nowr / 86400, (nowr / 3600) % 24,
-                 (nowr / 60) % 60, nowr % 60);
-      send_reply(sptr, RPL_STATSCONN, max_connection_count, max_client_count);
-      break;
-    }
-    case 'V':
-    case 'v':
-      report_servers_verbose(sptr, stat);
-      break;
-    case 'W':
-    case 'w':
-      calc_load(sptr);
-      break;
-    case 'X':
-    case 'x':
-#ifdef  DEBUGMODE
-      class_send_meminfo(sptr);
-      send_listinfo(sptr, parv[0]);
-#endif
-      break;
-    case 'Y':
-    case 'y':
-      report_classes(sptr);
-      break;
-    case 'Z':
-    case 'z':
-      count_memory(sptr, parv[0]);
-      break;
-
-    default:
-      stat = '*';
-      while (*infotext)
-        sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s", sptr, *infotext++);
-      break;
-  }
-  send_reply(sptr, RPL_ENDOFSTATS, stat);
-  return 0;
-}
-
index 5d145c9e9006a4269b1074ca72927ec1f7c67674..d21646542e19a57c919c25125074d484792f6525 100644 (file)
@@ -83,7 +83,7 @@
 
 #include "client.h"
 #include "ircd.h"
-#include "ircd_policy.h"
+#include "ircd_features.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "msg.h"
  */
 int m_time(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
-  if (hunt_server_cmd(sptr, CMD_TIME, cptr, HEAD_IN_SAND_REMOTE, ":%C", 1,
-                     parc, parv) != HUNTED_ISME)
+  if (hunt_server_cmd(sptr, CMD_TIME, cptr, feature_int(FEAT_HIS_REMOTE), ":%C",
+                      1, parc, parv)
+      != HUNTED_ISME)
     return 0;
 
   send_reply(sptr, RPL_TIME, cli_name(&me), TStime(), TSoffset, date((long)0));
index b8cfc82822d0616b4af43318a33c5de8b28a0842..a41745c0fca6941bab5ad56e7c2dac68a4a5337d 100644 (file)
@@ -161,14 +161,9 @@ int m_topic(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
       continue;
     }
-    /* Modeless Channels don't have topics */
-    if (IsModelessChannel(name))
-    {
-      send_reply(sptr, ERR_CHANOPRIVSNEEDED, chptr->chname);
-      continue;
-    }
 
-    if (!topic)                 /* only asking for topic */
+    /* only asking for topic */
+    if (!topic)
     {
       if (chptr->topic[0] == '\0')
        send_reply(sptr, RPL_NOTOPIC, chptr->chname);
@@ -211,13 +206,6 @@ int ms_topic(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
        send_reply(sptr,ERR_NOSUCHCHANNEL,name);
        continue;
     }
-    /* Modeless Channels don't have topics */
-    if (IsModelessChannel(name))
-    {
-      protocol_violation(sptr,"Attempted to topic modeless channel");
-      send_reply(sptr, ERR_CHANOPRIVSNEEDED, chptr->chname);
-      continue;
-    }
 
     /* Ignore requests for topics from remote servers */
     if (IsLocalChannel(name) && !MyUser(sptr))
index 4fa9d8a502acb2e3213facd567728182c91aeca2..34547ee5dceb33eee25202ce5da1fa2fe1eed4c6 100644 (file)
@@ -85,6 +85,7 @@
 #include "client.h"
 #include "hash.h"
 #include "ircd.h"
+#include "ircd_features.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "match.h"
@@ -120,18 +121,25 @@ int m_trace(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   int wilds;
   int dow;
 
-  if (parc < 2 || BadPtr(parv[1])) {
+  if (feature_bool(FEAT_HIS_TRACE))
+    return send_reply(cptr, ERR_NOPRIVILEGES);
+
+  if (parc < 2 || BadPtr(parv[1]))
+  {
     /* just "TRACE" without parameters. Must be from local client */
     parc = 1;
     acptr = &me;
     tname = cli_name(&me);
     i = HUNTED_ISME;
-  } else if (parc < 3 || BadPtr(parv[2])) {
+  }
+  else if (parc < 3 || BadPtr(parv[2]))
+  {
     /* No target specified. Make one before propagating. */
     parc = 2;
     tname = parv[1];
     if ((acptr = find_match_server(parv[1])) ||
-        ((acptr = FindClient(parv[1])) && !MyUser(acptr))) {
+        ((acptr = FindClient(parv[1])) && !MyUser(acptr)))
+    {
       if (IsUser(acptr))
         parv[2] = cli_name(cli_user(acptr)->server);
       else
@@ -141,7 +149,8 @@ int m_trace(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, IsServer(acptr),
                               "%s :%C", 2, parc, parv)) == HUNTED_NOSUCH)
         return 0;
-    } else
+    }
+    else
       i = HUNTED_ISME;
   } else {
     /* Got "TRACE <tname> :<target>" */
index 31dd236d9875649e2a4752d30b40be3cc52fb02f..a4d9c5532065335b666f045ecbeb7486068e11af 100644 (file)
@@ -85,7 +85,6 @@
 #include "hash.h"
 #include "ircd.h"
 #include "ircd_features.h"
-#include "ircd_policy.h"
 #include "ircd_reply.h"
 #include "ircd_snprintf.h"
 #include "ircd_string.h"
  * m_version - generic message handler
  *
  *   parv[0] = sender prefix
- *   parv[1] = remote server
+ *   parv[1] = servername
  */
 int m_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
-
-  if (parc > 1)
+  struct Client *acptr;
+  if (parc > 1 && (!(acptr = find_match_server(parv[1])) || !IsMe(acptr)))
     send_reply(sptr, ERR_NOPRIVILEGES);
   else
+  {
     send_reply(sptr, RPL_VERSION, version, debugmode, cli_name(&me),
-              debug_serveropts());
-
+               debug_serveropts());
+    send_supported(sptr);
+  }
   return 0;
 }
 
@@ -122,7 +123,7 @@ int m_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
  * mo_version - generic message handler
  *
  *   parv[0] = sender prefix
- *   parv[1] = remote server
+ *   parv[1] = servername
  */
 int mo_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
@@ -138,8 +139,10 @@ int mo_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     parv[1] = cli_name(acptr);
   }
 
-  if (hunt_server_cmd(sptr, CMD_VERSION, cptr, HEAD_IN_SAND_REMOTE, ":%C", 1,
-                     parc, parv) == HUNTED_ISME)
+  if (hunt_server_cmd(sptr, CMD_VERSION, cptr, feature_int(FEAT_HIS_REMOTE),
+                                                           ":%C", 1,
+                                                           parc, parv)
+                      == HUNTED_ISME)
   {
     send_reply(sptr, RPL_VERSION, version, debugmode, cli_name(&me),
               debug_serveropts());
@@ -153,7 +156,7 @@ int mo_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
  * ms_version - server message handler
  *
  *   parv[0] = sender prefix
- *   parv[1] = remote server
+ *   parv[1] = servername
  */
 int ms_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
index 9ff5a093b833421ddff266fe20b7f0270d9d4828..f05769bdb8a99e06fc474ec8b72821dc75604ff1 100644 (file)
@@ -105,7 +105,7 @@ int m_wallchops(struct Client* cptr, struct Client* sptr, int parc, char* parv[]
   assert(0 != cptr);
   assert(cptr == sptr);
 
-  cli_flags(sptr) &= ~FLAGS_TS8;
+  ClrFlag(sptr, FLAG_TS8);
 
   if (parc < 2 || EmptyString(parv[1]))
     return send_reply(sptr, ERR_NORECIPIENT, "WALLCHOPS");
@@ -120,7 +120,7 @@ int m_wallchops(struct Client* cptr, struct Client* sptr, int parc, char* parv[]
         return 0;
       sendcmdto_channel_butone(sptr, CMD_WALLCHOPS, chptr, cptr,
                               SKIP_DEAF | SKIP_BURST | SKIP_NONOPS,
-                              "%H :%s", chptr, parv[parc - 1]);
+                              "%H :%s", chptr, parv[parc - 1]);
     }
     else
       send_reply(sptr, ERR_CANNOTSENDTOCHAN, parv[1]);
diff --git a/ircd/m_wallvoices.c b/ircd/m_wallvoices.c
new file mode 100644 (file)
index 0000000..4aa3d86
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * IRC - Internet Relay Chat, ircd/m_wallvoices.c
+ * Copyright (c) 2002 hikari
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+/*
+ * 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 "channel.h"
+#include "client.h"
+#include "hash.h"
+#include "ircd.h"
+#include "ircd_reply.h"
+#include "ircd_string.h"
+#include "msg.h"
+#include "numeric.h"
+#include "numnicks.h"
+#include "s_user.h"
+#include "send.h"
+
+#include <assert.h>
+
+/*
+ * m_wallvoices - local generic message handler
+ */
+int m_wallvoices(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
+{
+  struct Channel *chptr;
+
+  assert(0 != cptr);
+  assert(cptr == sptr);
+
+  ClrFlag(sptr, FLAG_TS8);
+
+  if (parc < 2 || EmptyString(parv[1]))
+    return send_reply(sptr, ERR_NORECIPIENT, "WALLVOICES");
+
+  if (parc < 3 || EmptyString(parv[parc - 1]))
+    return send_reply(sptr, ERR_NOTEXTTOSEND);
+
+  if (IsChannelName(parv[1]) && (chptr = FindChannel(parv[1]))) {
+    if (client_can_send_to_channel(sptr, chptr)) {
+      if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
+          check_target_limit(sptr, chptr, chptr->chname, 0))
+        return 0;
+      sendcmdto_channel_butone(sptr, CMD_WALLVOICES, chptr, cptr,
+                              SKIP_DEAF | SKIP_BURST | SKIP_NONVOICES, 
+                              "%H :+ %s", chptr, parv[parc - 1]);
+    }
+    else
+      send_reply(sptr, ERR_CANNOTSENDTOCHAN, parv[1]);
+  }
+  else
+    send_reply(sptr, ERR_NOSUCHCHANNEL, parv[1]);
+
+  return 0;
+}
+
+/*
+ * ms_wallvoices - server message handler
+ */
+int ms_wallvoices(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
+{
+  struct Channel *chptr;
+  assert(0 != cptr);
+  assert(0 != sptr);
+
+  if (parc < 3 || !IsUser(sptr))
+    return 0;
+
+  if ((chptr = FindChannel(parv[1]))) {
+    if (client_can_send_to_channel(sptr, chptr)) {
+      sendcmdto_channel_butone(sptr, CMD_WALLVOICES, chptr, cptr,
+                              SKIP_DEAF | SKIP_BURST | SKIP_NONVOICES, 
+                              "%H :+ %s", chptr, parv[parc - 1]);
+    } else
+      send_reply(sptr, ERR_CANNOTSENDTOCHAN, parv[1]);
+  }
+  return 0;
+}
index cb8bf65e2680623580b3417b669d4b52af18a74f..d66775bd6eceb9829b837816aaa16d3cfc4dee80 100644 (file)
@@ -86,8 +86,8 @@
 #include "hash.h"
 #include "ircd.h"
 #include "ircd_chattr.h"
+#include "ircd_features.h"
 #include "ircd_log.h"
-#include "ircd_policy.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "match.h"
@@ -273,10 +273,8 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   if (!fields)
     counter = 7;
 
-#ifdef HEAD_IN_SAND_WHO_SERVERNAME
-  if (!IsAnOper(sptr))
+  if (feature_bool(FEAT_HIS_WHO_SERVERNAME) && !IsAnOper(sptr))
     matchsel &= ~WHO_FIELD_SER;
-#endif
 
   if (qrt && (fields & WHO_FIELD_QTY))
   {
@@ -390,7 +388,7 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
               && ((!(matchsel & WHO_FIELD_UID))
               || matchexec(cli_user(acptr)->username, mymask, minlen))
               && ((!(matchsel & WHO_FIELD_SER))
-              || (!(cli_flags(cli_user(acptr)->server) & FLAGS_MAP)))
+              || (!(HasFlag(cli_user(acptr)->server, FLAG_MAP))))
               && ((!(matchsel & WHO_FIELD_HOS))
               || matchexec(cli_user(acptr)->host, mymask, minlen))
               && ((!(matchsel & WHO_FIELD_HOS))
@@ -430,7 +428,7 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
             && ((!(matchsel & WHO_FIELD_UID))
             || matchexec(cli_user(acptr)->username, mymask, minlen))
             && ((!(matchsel & WHO_FIELD_SER))
-            || (!(cli_flags(cli_user(acptr)->server) & FLAGS_MAP)))
+                || (!(HasFlag(cli_user(acptr)->server, FLAG_MAP))))
             && ((!(matchsel & WHO_FIELD_HOS))
             || matchexec(cli_user(acptr)->host, mymask, minlen))
             && ((!(matchsel & WHO_FIELD_HOS))
index 0855164edbf998b7cb4aaccdae05cfe5f615667a..71a2b774e049a21e648a841d81b8856a759c44bd 100644 (file)
@@ -85,7 +85,7 @@
 #include "client.h"
 #include "hash.h"
 #include "ircd.h"
-#include "ircd_policy.h"
+#include "ircd_features.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "match.h"
@@ -183,12 +183,11 @@ static void do_whois(struct Client* sptr, struct Client *acptr, int parc)
         send_reply(sptr, RPL_WHOISCHANNELS, name, buf);
   }
 
-#ifdef HEAD_IN_SAND_WHOIS_SERVERNAME
-  if (!IsAnOper(sptr) && sptr != acptr)
-    send_reply(sptr, RPL_WHOISSERVER, name, HEAD_IN_SAND_SERVERNAME,
-              HEAD_IN_SAND_SERVERINFO);
+  if (feature_bool(FEAT_HIS_WHOIS_SERVERNAME) && !IsAnOper(sptr) &&
+      sptr != acptr)
+    send_reply(sptr, RPL_WHOISSERVER, name, feature_str(FEAT_HIS_SERVERNAME),
+               feature_str(FEAT_HIS_SERVERNAME));
   else
-#endif
     send_reply(sptr, RPL_WHOISSERVER, name, cli_name(a2cptr),
               cli_info(a2cptr));
 
@@ -204,19 +203,16 @@ static void do_whois(struct Client* sptr, struct Client *acptr, int parc)
     if (IsAccount(acptr))
       send_reply(sptr, RPL_WHOISACCOUNT, name, user->account);
 
-    if (HasHiddenHost(acptr) && IsAnOper(sptr))
+    if (HasHiddenHost(acptr) && (IsAnOper(sptr) || acptr == sptr))
       send_reply(sptr, RPL_WHOISACTUALLY, name, user->username,
-        user->realhost, ircd_ntoa((const char*) &(cli_ip(acptr))));
-   
+                 user->realhost, ircd_ntoa((const char*) &(cli_ip(acptr))));
+    
     /* Hint: if your looking to add more flags to a user, eg +h, here's
      *       probably a good place to add them :)
      */
      
-    if (MyConnect(acptr)
-#ifdef HEAD_IN_SAND_WHOIS_IDLETIME
-       && (sptr == acptr || IsAnOper(sptr) || parc >= 3)
-#endif
-       )
+    if (MyConnect(acptr) && (!feature_bool(FEAT_HIS_WHOIS_IDLETIME) ||
+                             (sptr == acptr || IsAnOper(sptr) || parc >= 3)))
        send_reply(sptr, RPL_WHOISIDLE, name, CurrentTime - user->last, 
                   cli_firsttime(acptr));
   }
@@ -361,21 +357,22 @@ int m_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
      * it with the correct servername - as is needed by hunt_server().
      * This is the secret behind the /whois nick nick trick.
      */
-#if HEAD_IN_SAND_REMOTE
-    /* If remote queries are disabled, then use the *second* parameter of
-     * of whois, so /whois nick nick still works.
-     */
-    if (!IsAnOper(sptr))
+    if (feature_int(FEAT_HIS_REMOTE))
     {
-      if (!FindUser(parv[2]))
+      /* If remote queries are disabled, then use the *second* parameter of
+       * of whois, so /whois nick nick still works.
+       */
+      if (!IsAnOper(sptr))
       {
-       send_reply(sptr, ERR_NOSUCHNICK, parv[2]);
-       send_reply(sptr, RPL_ENDOFWHOIS, parv[2]);
-       return 0;
+        if (!FindUser(parv[2]))
+        {
+          send_reply(sptr, ERR_NOSUCHNICK, parv[2]);
+          send_reply(sptr, RPL_ENDOFWHOIS, parv[2]);
+          return 0;
+        }
+        parv[1] = parv[2];
       }
-      parv[1] = parv[2];
     }
-#endif
 
     if (hunt_server_cmd(sptr, CMD_WHOIS, cptr, 0, "%C :%s", 1, parc, parv) !=
        HUNTED_ISME)
index adcaaeac2352a868e26ccfd072b964eea5381dff..f6a4cdfebb1e3515a277762d6cab4962c0580af8 100644 (file)
@@ -84,7 +84,7 @@
 #include "client.h"
 #include "hash.h"
 #include "ircd.h"
-#include "ircd_policy.h"
+#include "ircd_features.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "msg.h"
@@ -138,14 +138,11 @@ int m_whowas(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
        send_reply(sptr, RPL_WHOWASUSER, temp->name, temp->username,
                   (IsAnOper(sptr) && temp->realhost) ? temp->realhost :
                   temp->hostname, temp->realname);
-#ifdef HEAD_IN_SAND_WHOIS_SERVERNAME
-       if (!IsOper(sptr))
-         send_reply(sptr, RPL_WHOISSERVER, temp->name,
-                    HEAD_IN_SAND_SERVERNAME, myctime(temp->logoff));
-       else
-#endif
-         send_reply(sptr, RPL_WHOISSERVER, temp->name, temp->servername,
-                    myctime(temp->logoff));
+        send_reply(sptr, RPL_WHOISSERVER, temp->name,
+                   (feature_bool(FEAT_HIS_WHOIS_SERVERNAME) && !IsOper(sptr)) ?
+                     feature_str(FEAT_HIS_SERVERNAME) :
+                     temp->servername,
+                  myctime(temp->logoff));
         if (temp->away)
          send_reply(sptr, RPL_AWAY, temp->name, temp->away);
         cur++;
index 77119ff0ef7af64439b657180af586315caa9cf7..0a67438763d3304bc66314aecaffc42a6871107e 100644 (file)
@@ -237,15 +237,15 @@ void map_dump(struct Client *cptr, struct Client *server, char *mask, int prompt
   strcpy(p, "|-");
   for (lp = cli_serv(server)->down; lp; lp = lp->next)
     if (match(mask, cli_name(lp->value.cptr)))
-      cli_flags(lp->value.cptr) &= ~FLAGS_MAP;
+      ClrFlag(lp->value.cptr, FLAG_MAP);
     else
     {
-      cli_flags(lp->value.cptr) |= FLAGS_MAP;
+      SetFlag(lp->value.cptr, FLAG_MAP);
       cnt++;
     }
   for (lp = cli_serv(server)->down; lp; lp = lp->next)
   {
-    if ((cli_flags(lp->value.cptr) & FLAGS_MAP) == 0)
+    if (!HasFlag(lp->value.cptr, FLAG_MAP))
       continue;
     if (--cnt == 0)
       *p = '`';
index 393d1ee4c1d2768ce6ed243c75e1aa57027724a9..a2634b966c4ca1482e0ed25330adf70039c9a820 100644 (file)
@@ -41,6 +41,7 @@
 #include "s_conf.h"
 #include "s_debug.h"
 #include "s_user.h"
+#include "s_stats.h"
 #include "send.h"
 
 #include <assert.h>
@@ -63,6 +64,7 @@ motd_create(const char *hostmask, const char *path, int maxcount)
 {
   struct Motd* tmp;
   int type = MOTD_UNIVERSAL;
+  const char *s;
   
   assert(0 != path);
   
@@ -371,7 +373,7 @@ motd_clear(void)
 
 /* This is called to report T-lines */
 void
-motd_report(struct Client *to)
+motd_report(struct Client *to, struct StatDesc *sd, int stat, char *param)
 {
   struct Motd *ptr;
 
@@ -379,3 +381,49 @@ motd_report(struct Client *to)
     send_reply(to, SND_EXPLICIT | RPL_STATSTLINE, "T %s %s",
                ptr->hostmask, ptr->path);
 }
+
+void
+motd_memory_count(struct Client *cptr)
+{
+  struct Motd *ptr;
+  struct MotdCache *cache;
+  unsigned int mt = 0,   /* motd count */
+               mtm = 0,  /* memory consumed by motd */
+               mtc = 0,  /* motd cache count */
+               mtcm = 0, /* memory consumed by motd cache */
+               mtf = 0;  /* motd free list count */
+  if (MotdList.local)
+  {
+    mt++;
+    mtm += sizeof(struct Motd);
+    mtm += MotdList.local->path ? (strlen(MotdList.local->path) + 1) : 0;
+  }
+
+  if (MotdList.remote) 
+  {
+    mt++;
+    mtm += sizeof(struct Motd);
+    mtm += MotdList.remote->path ? (strlen(MotdList.remote->path) + 1) : 0;
+  }
+
+  for (ptr = MotdList.other; ptr; ptr = ptr->next)
+  {
+    mt++;
+    mtm += sizeof(struct Motd);
+    mtm += ptr->path ? (strlen(ptr->path) + 1) : 0;
+  }
+
+  for (cache = MotdList.cachelist; cache; cache = cache->next)
+  {
+    mtc++;
+    mtcm += sizeof(struct MotdCache) + (MOTD_LINESIZE * (cache->count - 1));
+  }
+
+  if (MotdList.freelist)
+    for (ptr = MotdList.freelist; ptr; ptr = ptr->next)
+      mtf++;
+
+  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
+             ":Motds %d(%zu) Cache %d(%zu) Free %d(%zu)",
+             mt, mtm, mtc, mtcm, mtf, (mtf * sizeof(struct Motd)));
+}
index e6ad9e4b5c72bfc3d29f890d31daf017e526ac98..043c8590fec7480214106e6e680018560882317d 100644 (file)
 #include "config.h"
 
 #include "msgq.h"
+#include "ircd.h"
 #include "ircd_alloc.h"
 #include "ircd_defs.h"
+#include "ircd_features.h"
+#include "ircd_reply.h"
 #include "ircd_snprintf.h"
+#include "numeric.h"
+#include "send.h"
 #include "s_debug.h"
+#include "s_stats.h"
 
 #include <assert.h>
 #include <stdarg.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/uio.h>   /* struct iovec */
 
+#define MB_BASE_SHIFT  5
+#define MB_MAX_SHIFT   9
+
 struct MsgBuf {
   struct MsgBuf *next;         /* next msg in global queue */
   struct MsgBuf **prev_p;      /* what points to us in linked list */
+  struct MsgBuf *real;         /* the actual MsgBuf we're attaching */
   unsigned int ref;            /* reference count */
   unsigned int length;         /* length of message */
-  char msg[BUFSIZE + 1];       /* the message */
+  unsigned int power;          /* size of buffer (power of 2) */
+  char msg[1];                 /* the message */
 };
 
+#define bufsize(buf)   (1 << (buf)->power)
+
 struct Msg {
   struct Msg *next;            /* next msg */
   unsigned int sent;           /* bytes in msg that have already been sent */
   struct MsgBuf *msg;          /* actual message in queue */
 };
 
-static struct {
-  struct MsgBuf *msgs;
-  struct MsgBuf *free_mbs;
-  struct Msg *free_msgs;
-} MQData = { 0, 0, 0 };
+struct MsgSizes {
+  unsigned int msgs;           /* total number of messages */
+  unsigned int sizes[BUFSIZE]; /* histogram of message sizes */
+};
 
-struct MsgCounts msgBufCounts = { 0, 0 };
-struct MsgCounts msgCounts = { 0, 0 };
+static struct {
+  struct MsgBuf *msglist;      /* list of in-use MsgBuf's */
+  struct {
+    unsigned int alloc;                /* number of Msg's allocated */
+    unsigned int used;         /* number of Msg's in use */
+    struct Msg *free;          /* freelist of Msg's */
+  } msgs;
+  size_t tot_bufsize;          /* total amount of memory in buffers */
+  struct {
+    unsigned int alloc;                /* total MsgBuf's of this size */
+    unsigned int used;         /* number of MsgBuf's of this size in use */
+    struct MsgBuf *free;       /* list of free MsgBuf's */
+  } msgBufs[MB_MAX_SHIFT - MB_BASE_SHIFT + 1];
+  struct MsgSizes sizes;       /* histogram of message sizes */
+} MQData;
 
 /*
  * This routine is used to remove a certain amount of data from a given
@@ -86,10 +112,10 @@ msgq_delmsg(struct MsgQ *mq, struct MsgQList *qlist, unsigned int *length_p)
     else
       qlist->head = m->next; /* just shift the list down some */
 
-    msgCounts.used--; /* struct Msg is not in use anymore */
+    MQData.msgs.used--; /* struct Msg is not in use anymore */
 
-    m->next = MQData.free_msgs; /* throw it onto the free list */
-    MQData.free_msgs = m;
+    m->next = MQData.msgs.free; /* throw it onto the free list */
+    MQData.msgs.free = m;
   } else {
     mq->length -= *length_p; /* decrement queue length */
     m->sent += *length_p; /* this much of the message has been sent */
@@ -205,6 +231,76 @@ msgq_mapiov(const struct MsgQ *mq, struct iovec *iov, int count,
   return i;
 }
 
+/*
+ * This is a helper routine to allocate a buffer
+ */
+static struct MsgBuf *
+msgq_alloc(struct MsgBuf *in_mb, int length)
+{
+  struct MsgBuf *mb;
+  int power;
+
+  /* Find the power of two size that will accomodate the message */
+  for (power = MB_BASE_SHIFT; power < MB_MAX_SHIFT + 1; power++)
+    if ((length - 1) >> power == 0)
+      break;
+  assert((1 << power) >= length);
+  assert((1 << power) <= 512);
+  length = 1 << power; /* reset the length */
+
+  /* If the message needs a buffer of exactly the existing size, just use it */
+  if (in_mb && in_mb->power == power) {
+    in_mb->real = in_mb; /* real buffer is this buffer */
+    return in_mb;
+  }
+
+  /* Try popping one off the freelist first */
+  if ((mb = MQData.msgBufs[power - MB_BASE_SHIFT].free)) {
+    MQData.msgBufs[power - MB_BASE_SHIFT].free = mb->next;
+  } else if (MQData.tot_bufsize < feature_int(FEAT_BUFFERPOOL)) {
+    /* Allocate another if we won't bust the BUFFERPOOL */
+    Debug((DEBUG_MALLOC, "Allocating MsgBuf of length %d (total size %zu)",
+          length, sizeof(struct MsgBuf) + length));
+    mb = (struct MsgBuf *)MyMalloc(sizeof(struct MsgBuf) + length);
+    MQData.msgBufs[power - MB_BASE_SHIFT].alloc++;
+    mb->power = power; /* remember size */
+    MQData.tot_bufsize += length;
+  }
+
+  if (mb) {
+    MQData.msgBufs[power - MB_BASE_SHIFT].used++; /* how many are we using? */
+
+    mb->real = 0; /* essential initializations */
+    mb->ref = 1;
+
+    if (in_mb) /* remember who's the *real* buffer */
+      in_mb->real = mb;
+  } else if (in_mb) /* just use the input buffer */
+    mb = in_mb->real = in_mb;
+
+  return mb; /* return the buffer */
+}
+
+/*
+ * This routine simply empties the free list
+ */
+static void
+msgq_clear_freembs(void)
+{
+  struct MsgBuf *mb;
+  int i;
+
+  /* Walk through the various size classes */
+  for (i = MB_BASE_SHIFT; i < MB_MAX_SHIFT + 1; i++)
+    /* walk down the free list */
+    while ((mb = MQData.msgBufs[i - MB_BASE_SHIFT].free)) {
+      MQData.msgBufs[i - MB_BASE_SHIFT].free = mb->next; /* shift free list */
+      MQData.msgBufs[i - MB_BASE_SHIFT].alloc--; /* reduce allocation count */
+      MQData.tot_bufsize -= 1 << i; /* reduce total buffer allocation count */
+      MyFree(mb); /* and free the buffer */
+    }
+}
+
 /*
  * This routine builds a struct MsgBuf with the appropriate contents
  * and returns it; this saves us from having to worry about the contents
@@ -217,33 +313,62 @@ msgq_vmake(struct Client *dest, const char *format, va_list vl)
 
   assert(0 != format);
 
-  if (!(mb = MQData.free_mbs)) { /* do I need to allocate one? */
-    mb = (struct MsgBuf *)MyMalloc(sizeof(struct MsgBuf));
-    msgBufCounts.alloc++; /* we allocated another */
-  } else /* shift the free list */
-    MQData.free_mbs = MQData.free_mbs->next;
-
-  msgBufCounts.used++; /* we're using another */
+  if (!(mb = msgq_alloc(0, BUFSIZE))) {
+    if (feature_bool(FEAT_HAS_FERGUSON_FLUSHER)) {
+      /*
+       * from "Married With Children" episode were Al bought a REAL toilet
+       * on the black market because he was tired of the wimpy water
+       * conserving toilets they make these days --Bleep
+       */
+      /*
+       * Apparently this doesn't work, the server _has_ to
+       * dump a few clients to handle the load. A fully loaded
+       * server cannot handle a net break without dumping some
+       * clients. If we flush the connections here under a full
+       * load we may end up starving the kernel for mbufs and
+       * crash the machine
+       */
+      /*
+       * attempt to recover from buffer starvation before
+       * bailing this may help servers running out of memory
+       */
+      flush_connections(0);
+      mb = msgq_alloc(0, BUFSIZE);
+    }
+    if (!mb) { /* OK, try clearing the buffer free list */
+      msgq_clear_freembs();
+      mb = msgq_alloc(0, BUFSIZE);
+    }
+    if (!mb) { /* OK, try killing a client */
+      kill_highest_sendq(0); /* Don't kill any server connections */
+      mb = msgq_alloc(0, BUFSIZE);
+    }
+    if (!mb) { /* hmmm... */
+      kill_highest_sendq(1); /* Try killing a server connection now */
+      mb = msgq_alloc(0, BUFSIZE);
+    }
+    if (!mb) /* AIEEEE! */
+      server_panic("Unable to allocate buffers!");
+  }
 
-  mb->next = MQData.msgs; /* initialize the msgbuf */
-  mb->prev_p = &MQData.msgs;
-  mb->ref = 1;
+  mb->next = MQData.msglist; /* initialize the msgbuf */
+  mb->prev_p = &MQData.msglist;
 
   /* fill the buffer */
-  mb->length = ircd_vsnprintf(dest, mb->msg, sizeof(mb->msg) - 2, format, vl);
+  mb->length = ircd_vsnprintf(dest, mb->msg, bufsize(mb) - 1, format, vl);
 
-  if (mb->length > sizeof(mb->msg) - 3)
-    mb->length = sizeof(mb->msg) - 3;
+  if (mb->length > bufsize(mb) - 2)
+    mb->length = bufsize(mb) - 2;
 
   mb->msg[mb->length++] = '\r'; /* add \r\n to buffer */
   mb->msg[mb->length++] = '\n';
   mb->msg[mb->length] = '\0'; /* not strictly necessary */
 
-  assert(mb->length < sizeof(mb->msg));
+  assert(mb->length <= bufsize(mb));
 
-  if (MQData.msgs) /* link it into the list */
-    MQData.msgs->prev_p = &mb->next;
-  MQData.msgs = mb;
+  if (MQData.msglist) /* link it into the list */
+    MQData.msglist->prev_p = &mb->next;
+  MQData.msglist = mb;
 
   return mb;
 }
@@ -271,25 +396,26 @@ msgq_append(struct Client *dest, struct MsgBuf *mb, const char *format, ...)
 
   assert(0 != mb);
   assert(0 != format);
+  assert(0 == mb->real);
 
   assert(2 < mb->length);
-  assert(sizeof(mb->msg) > mb->length);
+  assert(bufsize(mb) >= mb->length);
 
   mb->length -= 2; /* back up to before \r\n */
 
   va_start(vl, format); /* append to the buffer */
   mb->length += ircd_vsnprintf(dest, mb->msg + mb->length,
-                              sizeof(mb->msg) - 2 - mb->length, format, vl);
+                              bufsize(mb) - mb->length - 1, format, vl);
   va_end(vl);
 
-  if (mb->length > sizeof(mb->msg) - 3)
-    mb->length = sizeof(mb->msg) - 3;
+  if (mb->length > bufsize(mb) - 2)
+    mb->length = bufsize(mb) - 2;
 
   mb->msg[mb->length++] = '\r'; /* add \r\n to buffer */
   mb->msg[mb->length++] = '\n';
   mb->msg[mb->length] = '\0'; /* not strictly necessary */
 
-  assert(mb->length < sizeof(mb->msg));
+  assert(mb->length <= bufsize(mb));
 }
 
 /*
@@ -301,19 +427,22 @@ msgq_clean(struct MsgBuf *mb)
 {
   assert(0 != mb);
   assert(0 < mb->ref);
-  assert(0 != mb->prev_p);
 
   if (!--mb->ref) { /* deallocate the message */
-    *mb->prev_p = mb->next; /* clip it out of active MsgBuf's list */
-    if (mb->next)
-      mb->next->prev_p = mb->prev_p;
+    if (mb->prev_p) {
+      *mb->prev_p = mb->next; /* clip it out of active MsgBuf's list */
+      if (mb->next)
+       mb->next->prev_p = mb->prev_p;
+    }
 
-    mb->next = MQData.free_mbs; /* add it to free list */
-    MQData.free_mbs = mb;
+    if (mb->real && mb->real != mb) /* clean up the real buffer */
+      msgq_clean(mb->real);
 
-    mb->prev_p = 0;
+    mb->next = MQData.msgBufs[mb->power - MB_BASE_SHIFT].free;
+    MQData.msgBufs[mb->power - MB_BASE_SHIFT].free = mb;
+    MQData.msgBufs[mb->power - MB_BASE_SHIFT].used--;
 
-    msgBufCounts.used--; /* decrement the usage count */
+    mb->prev_p = 0;
   }
 }
 
@@ -329,26 +458,56 @@ msgq_add(struct MsgQ *mq, struct MsgBuf *mb, int prio)
   assert(0 != mq);
   assert(0 != mb);
   assert(0 < mb->ref);
+  assert(0 < mb->length);
 
-  Debug((DEBUG_SEND, "Adding buffer %p [%.*s] to %s queue", mb,
-        mb->length - 2, mb->msg, prio ? "priority" : "normal"));
+  Debug((DEBUG_SEND, "Adding buffer %p [%.*s] length %u to %s queue", mb,
+        mb->length - 2, mb->msg, mb->length, prio ? "priority" : "normal"));
 
   qlist = prio ? &mq->prio : &mq->queue;
 
-  if (!(msg = MQData.free_msgs)) { /* do I need to allocate one? */
+  if (!(msg = MQData.msgs.free)) { /* do I need to allocate one? */
     msg = (struct Msg *)MyMalloc(sizeof(struct Msg));
-    msgCounts.alloc++; /* we allocated another */
+    MQData.msgs.alloc++; /* we allocated another */
   } else /* shift the free list */
-    MQData.free_msgs = MQData.free_msgs->next;
+    MQData.msgs.free = MQData.msgs.free->next;
 
-  msgCounts.used++; /* we're using another */
+  MQData.msgs.used++; /* we're using another */
 
   msg->next = 0; /* initialize the msg */
   msg->sent = 0;
-  msg->msg = mb;
 
+  /* Get the real buffer, allocating one if necessary */
+  if (!mb->real) {
+    struct MsgBuf *tmp;
+
+    MQData.sizes.msgs++; /* update histogram counts */
+    MQData.sizes.sizes[mb->length - 1]++;
+
+    tmp = msgq_alloc(mb, mb->length); /* allocate a close-fitting buffer */
+
+    if (tmp != mb) { /* OK, prepare the new "real" buffer */
+      Debug((DEBUG_SEND, "Copying old buffer %p [%.*s] length %u into new "
+            "buffer %p size %u", mb, mb->length - 2, mb->msg, mb->length,
+            tmp, bufsize(tmp)));
+      memcpy(tmp->msg, mb->msg, mb->length + 1); /* copy string over */
+      tmp->length = mb->length;
+
+      tmp->next = mb->next; /* replace it in the list, now */
+      if (tmp->next)
+       tmp->next->prev_p = &tmp->next;
+      tmp->prev_p = mb->prev_p;
+      *tmp->prev_p = tmp;
+
+      mb->next = 0; /* this one's no longer in the list */
+      mb->prev_p = 0;
+    }
+  }
+
+  mb = mb->real; /* work with the real buffer */
   mb->ref++; /* increment the ref count on the buffer */
 
+  msg->msg = mb; /* point at the real message buffer now */
+
   if (!qlist->head) /* queue list was empty; head and tail point to msg */
     qlist->head = qlist->tail = msg;
   else {
@@ -366,18 +525,39 @@ msgq_add(struct MsgQ *mq, struct MsgBuf *mb, int prio)
  * This is for reporting memory usage by the msgq system.
  */
 void
-msgq_count_memory(size_t *msg_alloc, size_t *msg_used, size_t *msgbuf_alloc,
-                 size_t *msgbuf_used)
+msgq_count_memory(struct Client *cptr, size_t *msg_alloc, size_t *msgbuf_alloc)
 {
+  int i;
+  size_t total = 0, size;
+
+  assert(0 != cptr);
   assert(0 != msg_alloc);
-  assert(0 != msg_used);
   assert(0 != msgbuf_alloc);
-  assert(0 != msgbuf_used);
 
-  *msg_alloc = msgCounts.alloc * sizeof(struct Msg);
-  *msg_used = msgCounts.used * sizeof(struct Msg);
-  *msgbuf_alloc = msgCounts.alloc * sizeof(struct MsgBuf);
-  *msgbuf_used = msgCounts.used * sizeof(struct MsgBuf);
+  /* Data for Msg's is simple, so just send it */
+  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
+            ":Msgs allocated %d(%zu) used %d(%zu)", MQData.msgs.alloc,
+            MQData.msgs.alloc * sizeof(struct Msg), MQData.msgs.used,
+            MQData.msgs.used * sizeof(struct Msg));
+  /* count_memory() wants to know the total */
+  *msg_alloc = MQData.msgs.alloc * sizeof(struct Msg);
+
+  /* Ok, now walk through each size class */
+  for (i = MB_BASE_SHIFT; i < MB_MAX_SHIFT + 1; i++) {
+    size = sizeof(struct MsgBuf) + (1 << i); /* total size of a buffer */
+
+    /* Send information for this buffer size class */
+    send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
+              ":MsgBufs of size %zu allocated %d(%zu) used %d(%zu)", 1 << i,
+              MQData.msgBufs[i - MB_BASE_SHIFT].alloc,
+              MQData.msgBufs[i - MB_BASE_SHIFT].alloc * size,
+              MQData.msgBufs[i - MB_BASE_SHIFT].used,
+              MQData.msgBufs[i - MB_BASE_SHIFT].used * size);
+
+    /* count_memory() wants to know the total */
+    total += MQData.msgBufs[i - MB_BASE_SHIFT].alloc * size;
+  }
+  *msgbuf_alloc = total;
 }
 
 /*
@@ -388,5 +568,28 @@ msgq_bufleft(struct MsgBuf *mb)
 {
   assert(0 != mb);
 
-  return sizeof(mb->msg) - mb->length - 1; /* \r\n counted in mb->length */
+  return bufsize(mb) - mb->length; /* \r\n counted in mb->length */
+}
+
+/*
+ * This just generates and sends a histogram of message lengths to the
+ * requesting client
+ */
+void
+msgq_histogram(struct Client *cptr, struct StatDesc *sd, int stat, char *param)
+{
+  struct MsgSizes tmp = MQData.sizes; /* All hail structure copy! */
+  int i;
+
+  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
+            ":Histogram of message lengths (%lu messages)", tmp.msgs);
+  for (i = 0; i + 16 <= BUFSIZE; i += 16)
+    send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":% 4d: %lu %lu %lu %lu "
+              "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", i + 1,
+              tmp.sizes[i +  0], tmp.sizes[i +  1], tmp.sizes[i +  2],
+              tmp.sizes[i +  3], tmp.sizes[i +  4], tmp.sizes[i +  5],
+              tmp.sizes[i +  6], tmp.sizes[i +  7], tmp.sizes[i +  8],
+              tmp.sizes[i +  9], tmp.sizes[i + 10], tmp.sizes[i + 11],
+              tmp.sizes[i + 12], tmp.sizes[i + 13], tmp.sizes[i + 14],
+              tmp.sizes[i + 15]);
 }
index cbba746a1d7b1d8b3c24497628a1074194fecad2..8574fe71773f6d5b7ca69c9285407bca217cae08 100644 (file)
@@ -340,11 +340,13 @@ int markMatchexServer(const char *cmask, int minlen)
   struct Client *acptr;
 
   for (i = 0; i < lastNNServer; i++) {
-    if ((acptr = server_list[i])) {
+    if ((acptr = server_list[i]))
+    {
       if (matchexec(cli_name(acptr), cmask, minlen))
-        cli_flags(acptr) &= ~FLAGS_MAP;
-      else {
-        cli_flags(acptr) |= FLAGS_MAP;
+        ClrFlag(acptr, FLAG_MAP);
+      else
+      {
+        SetFlag(acptr, FLAG_MAP);
         cnt++;
       }
     }
index 22016f1abc24fc05bf23822b76c834a1a4930add..0cc35a428b4530af50f8931f8695b9422167db8c 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/time.h>
 
 char *militime(char* sec, char* usec)
@@ -58,3 +59,25 @@ char *militime(char* sec, char* usec)
   return timebuf;
 }
 
+char *militime_float(char* start)
+{
+  struct timeval tv;
+  static char timebuf[18];
+  char *p;
+
+  gettimeofday(&tv, NULL);
+  if (start)
+  {
+    if ((p = strchr(start, '.')))
+    {
+      p++;
+      sprintf(timebuf, "%ld",
+          (tv.tv_sec - atoi(start)) * 1000 + (tv.tv_usec - atoi(p)) / 1000);
+    }
+    else 
+      strcpy(timebuf, "0");
+  }
+  else
+    sprintf(timebuf, "%ld.%ld", tv.tv_sec, tv.tv_usec);
+  return timebuf;
+}
index d5cd49d51f3eead0d80ea23820156a3acede1a5e..4a1d7f6161bc18ab4c7ac8da3183af0e41d5d5eb 100644 (file)
@@ -30,7 +30,6 @@
 #include "ircd_alloc.h"
 #include "ircd_chattr.h"
 #include "ircd_features.h"
-#include "ircd_policy.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "msg.h"
@@ -93,6 +92,13 @@ struct Message msgtab[] = {
     /* UNREG, CLIENT, SERVER, OPER, SERVICE */
     { m_unregistered, m_wallchops, ms_wallchops, m_wallchops, m_ignore }
   },
+  {
+    MSG_WALLVOICES,
+    TOK_WALLVOICES,
+    0, MAXPARA, MFLG_SLOW, 0,
+    /* UNREG, CLIENT, SERVER, OPER, SERVICE */
+    { m_unregistered, m_wallvoices, ms_wallvoices, m_wallvoices, m_ignore }
+  },
   {
     MSG_CPRIVMSG,
     TOK_CPRIVMSG,
@@ -315,11 +321,7 @@ struct Message msgtab[] = {
     TOK_TRACE,
     0, MAXPARA, MFLG_SLOW, 0,
     /* UNREG, CLIENT, SERVER, OPER, SERVICE */
-#ifdef HEAD_IN_SAND_TRACE
-    { m_unregistered, m_not_oper, ms_trace, mo_trace, m_ignore }
-#else
     { m_unregistered, m_trace, ms_trace, mo_trace, m_ignore }
-#endif
   },
   {
     MSG_PASS,
@@ -382,7 +384,7 @@ struct Message msgtab[] = {
     TOK_MAP,
     0, MAXPARA, MFLG_SLOW, 0,
     /* UNREG, CLIENT, SERVER, OPER, SERVICE */
-    { m_unregistered, m_map, m_ignore, mo_map, m_ignore }
+    { m_unregistered, m_map, m_ignore, m_map, m_ignore }
   },
   {
     MSG_VERSION,
@@ -396,18 +398,14 @@ struct Message msgtab[] = {
     TOK_STATS,
     0, MAXPARA, MFLG_SLOW, 0,
     /* UNREG, CLIENT, SERVER, OPER, SERVICE */
-    { m_unregistered, m_stats, ms_stats, mo_stats, m_ignore }
+    { m_unregistered, m_stats, m_stats, m_stats, m_ignore }
   },
   {
     MSG_LINKS,
     TOK_LINKS,
     0, MAXPARA, MFLG_SLOW, 0,
     /* UNREG, CLIENT, SERVER, OPER, SERVICE */
-#ifdef HEAD_IN_SAND_LINKS
-    { m_unregistered, m_links_redirect, m_links, m_links, m_ignore }
-#else
-    { m_unregistered, m_links, m_links, m_links, m_ignore }
-#endif
+    { m_unregistered, m_links, ms_links, m_links, m_ignore }
   },
   {
     MSG_ADMIN,
@@ -577,6 +575,13 @@ struct Message msgtab[] = {
     /* UNREG, CLIENT, SERVER, OPER, SERVICE */
     { m_ignore, m_ignore, ms_account, m_ignore, m_ignore }
   },
+  {
+    MSG_ASLL,
+    TOK_ASLL,
+    0, MAXPARA, MFLG_SLOW, 0,
+    /* UNREG, CLIENT, SERVER, OPER, SERVICE */
+    { m_ignore, m_not_oper, ms_asll, mo_asll, m_ignore }
+   },
   /* This command is an alias for QUIT during the unregistered part of
    * of the server.  This is because someone jumping via a broken web
    * proxy will send a 'POST' as their first command - which we will
index e85b228a363c6490b40b14d1480627b724a4f28e..7170167101551fc72357cea2d0ccfc0b2f4ffd3f 100644 (file)
@@ -82,7 +82,7 @@ memxor(void *dest, void *src, int n)
   unsigned char *d = (unsigned char *)dest;
   unsigned char *s = (unsigned char *)src;
 
-  while (--n)
+  while (n--)
     d[n] ^= s[n];
 }
 
index 17dce053b1627e5e382ae52aeb4f53f755bf6c24..b9019ecc284d1f30b9c1e25400cadd98230c952e 100644 (file)
@@ -80,8 +80,9 @@ static struct {
   { "NOTICE AUTH :*** Checking Ident\r\n",                 33 },
   { "NOTICE AUTH :*** Got ident response\r\n",             37 },
   { "NOTICE AUTH :*** No ident response\r\n",              36 },
-  { "NOTICE AUTH :*** Your forward and reverse DNS do not match, " \
-    "ignoring hostname.\r\n",                              80 }
+  { "NOTICE AUTH :*** Your forward and reverse DNS do not match, "
+    "ignoring hostname.\r\n",                              80 },
+  {"NOTICE AUTH :*** Invalid hostname\r\n",                35 }
 };
 
 typedef enum {
@@ -92,7 +93,8 @@ typedef enum {
   REPORT_DO_ID,
   REPORT_FIN_ID,
   REPORT_FAIL_ID,
-  REPORT_IP_MISMATCH
+  REPORT_IP_MISMATCH,
+  REPORT_INVAL_DNS
 } ReportType;
 
 #define sendheader(c, r) \
@@ -108,6 +110,24 @@ static void unlink_auth_request(struct AuthRequest* request,
                                 struct AuthRequest** list);
 void free_auth_request(struct AuthRequest* auth);
 
+/* auth_verify_hostname - verify that a hostname is valid, i.e., only
+ * contains characters valid for a hostname and that a hostname is not
+ * too long.
+ */
+static int
+auth_verify_hostname(char *host, int maxlen)
+{
+  int i;
+
+  /* Walk through the host name */
+  for (i = 0; host[i]; i++)
+    /* If it's not a hostname character or if it's too long, return false */
+    if (!IsHostChar(host[i]) || i >= maxlen)
+      return 0;
+
+  return 1; /* it's a valid hostname */
+}
+
 /*
  * auth_timeout - timeout a given auth request
  */
@@ -353,7 +373,13 @@ static void auth_dns_callback(void* vptr, struct DNSReply* reply)
        return;
       }
     }
-    else {
+    else if (!auth_verify_hostname(hp->h_name, HOSTLEN))
+    {
+      if (IsUserPort(auth->client))
+        sendheader(auth->client, REPORT_INVAL_DNS);
+    }
+    else
+    {
       ++reply->ref_count;
       cli_dns_reply(auth->client) = reply;
       ircd_strncpy(cli_sockhost(auth->client), hp->h_name, HOSTLEN);
index 0b5324bb842607c246eadf0dc2389d35584d3d62..282bb5eaebfcc7e1212f23b9b42df31acf1db08f 100644 (file)
@@ -358,7 +358,7 @@ unsigned int deliver_it(struct Client *cptr, struct MsgQ *buf)
 
   switch (os_sendv_nonb(cli_fd(cptr), buf, &bytes_count, &bytes_written)) {
   case IO_SUCCESS:
-    cli_flags(cptr) &= ~FLAGS_BLOCKED;
+    ClrFlag(cptr, FLAG_BLOCKED);
 
     cli_sendB(cptr) += bytes_written;
     cli_sendB(&me)  += bytes_written;
@@ -375,14 +375,14 @@ unsigned int deliver_it(struct Client *cptr, struct MsgQ *buf)
      * say it was blocked
      */
     if (bytes_written < bytes_count)
-      cli_flags(cptr) |= FLAGS_BLOCKED;
+      SetFlag(cptr, FLAG_BLOCKED);
     break;
   case IO_BLOCKED:
-    cli_flags(cptr) |= FLAGS_BLOCKED;
+    SetFlag(cptr, FLAG_BLOCKED);
     break;
   case IO_FAILURE:
     cli_error(cptr) = errno;
-    cli_flags(cptr) |= FLAGS_DEADSOCKET;
+    SetFlag(cptr, FLAG_DEADSOCKET);
     break;
   }
   return bytes_written;
@@ -460,7 +460,7 @@ static int completed_connection(struct Client* cptr)
    * Make us timeout after twice the timeout for DNS look ups
    */
   cli_lasttime(cptr) = CurrentTime;
-  cli_flags(cptr) |= FLAGS_PINGSENT;
+  SetFlag(cptr, FLAG_PINGSENT);
 
   sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s :%s",
                 cli_name(&me), cli_serv(&me)->timestamp, newts,
@@ -540,7 +540,7 @@ void close_connection(struct Client *cptr)
     socket_del(&(cli_socket(cptr))); /* queue a socket delete */
     cli_fd(cptr) = -1;
   }
-  cli_flags(cptr) |= FLAGS_DEADSOCKET;
+  SetFlag(cptr, FLAG_DEADSOCKET);
 
   MsgQClear(&(cli_sendQ(cptr)));
   client_drop_sendq(cli_connect(cptr));
@@ -704,18 +704,21 @@ static int read_packet(struct Client *cptr, int socket_ready)
        DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD))) {
     switch (os_recv_nonb(cli_fd(cptr), readbuf, sizeof(readbuf), &length)) {
     case IO_SUCCESS:
-      if (length) {
-        cli_lasttime(cptr) = CurrentTime;
+      if (length)
+      {
+        if (!IsServer(cptr))
+          cli_lasttime(cptr) = CurrentTime;
         if (cli_lasttime(cptr) > cli_since(cptr))
           cli_since(cptr) = cli_lasttime(cptr);
-        cli_flags(cptr) &= ~(FLAGS_PINGSENT | FLAGS_NONL);
+        ClrFlag(cptr, FLAG_PINGSENT);
+        ClrFlag(cptr, FLAG_NONL);
       }
       break;
     case IO_BLOCKED:
       break;
     case IO_FAILURE:
       cli_error(cptr) = errno;
-      /* cptr->flags |= FLAGS_DEADSOCKET; */
+      /* SetFlag(cpt, FLAG_DEADSOCKET); */
       return 0;
     }
   }
@@ -754,10 +757,10 @@ static int read_packet(struct Client *cptr, int socket_ready)
        * deletes the rest of the buffer contents.
        * -avalon
        */
-      if (dolen = 0)
+      if (dolen == 0)
       {
         if (DBufLength(&(cli_recvQ(cptr))) < 510)
-          cli_flags(cptr) |= FLAGS_NONL;
+          SetFlag(cptr, FLAG_NONL);
         else
           DBufClear(&(cli_recvQ(cptr)));
       }
@@ -769,15 +772,15 @@ static int read_packet(struct Client *cptr, int socket_ready)
        */
       if (IsHandshake(cptr) || IsServer(cptr))
       {
-        while (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr))
+        while (-1)
         {
           dolen = dbuf_get(&(cli_recvQ(cptr)), readbuf, sizeof(readbuf));
-          if (dolen < 0)
+          if (dolen <= 0)
             return 1;
           else if (dolen == 0)
           {
             if (DBufLength(&(cli_recvQ(cptr))) < 510)
-              cli_flags(cptr) |= FLAGS_NONL;
+              SetFlag(cptr, FLAG_NONL);
             else
               DBufClear(&(cli_recvQ(cptr)));
           }
@@ -1022,7 +1025,7 @@ static void client_sock_callback(struct Event* ev)
   case ET_EOF: /* end of file on socket */
     Debug((DEBUG_ERROR, "READ ERROR: fd = %d %d", cli_fd(cptr),
           cli_error(cptr)));
-    cli_flags(cptr) |= FLAGS_DEADSOCKET;
+    SetFlag(cptr, FLAG_DEADSOCKET);
     if ((IsServer(cptr) || IsHandshake(cptr)) && cli_error(cptr) == 0) {
       exit_client_msg(cptr, cptr, &me, "Server %s closed the connection (%s)",
                      cli_name(cptr), cli_serv(cptr)->last_error_msg);
@@ -1034,7 +1037,7 @@ static void client_sock_callback(struct Event* ev)
     break;
 
   case ET_WRITE: /* socket is writable */
-    cli_flags(cptr) &= ~FLAGS_BLOCKED;
+    ClrFlag(cptr, FLAG_BLOCKED);
     if (cli_listing(cptr) && MsgQLength(&(cli_sendQ(cptr))) < 2048)
       list_next_channels(cptr, 64);
     Debug((DEBUG_SEND, "Sending queued data to %C", cptr));
index 21fa6aca7c8e904a09928dc23f973bbc3d2d0e1d..d09dfd8c8b8b29d8b1168c4058c06ffd83983607 100644 (file)
 #include <errno.h>
 #include <fcntl.h>
 #include <netdb.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#include <stdio.h>
 
 #ifndef INADDR_NONE
 #define INADDR_NONE 0xffffffff
 #endif
 
-struct ConfItemGlobalConfList  = 0;
+struct ConfItem  *GlobalConfList  = 0;
 int              GlobalConfCount = 0;
+struct qline     *GlobalQuarantineList = 0;
 
 void yyparse(void);
 int conf_fd, lineno;
@@ -238,7 +239,8 @@ static struct DNSReply* conf_dns_lookup(struct ConfItem* aconf)
  * Do (start) DNS lookups of all hostnames in the conf line and convert
  * an IP addresses in a.b.c.d number for to IP#s.
  */
-void lookup_confhost(struct ConfItem *aconf)
+void
+lookup_confhost(struct ConfItem *aconf)
 {
   struct DNSReply* reply;
 
@@ -399,7 +401,7 @@ enum AuthorizationCheckResult attach_iline(struct Client*  cptr)
         uhost[sizeof(uhost) - 1] = 0;
         if (0 == match(aconf->name, uhost)) {
           if (strchr(uhost, '@'))
-            cli_flags(cptr) |= FLAGS_DOID;
+            SetFlag(cptr, FLAG_DOID);
           return check_limit_and_attach(cptr, aconf);
         }
       }
@@ -416,7 +418,7 @@ enum AuthorizationCheckResult attach_iline(struct Client*  cptr)
     if (match(aconf->host, uhost))
       continue;
     if (strchr(uhost, '@'))
-      cli_flags(cptr) |= FLAGS_DOID;
+      SetFlag(cptr, FLAG_DOID);
 
     return check_limit_and_attach(cptr, aconf);
   }
@@ -922,6 +924,43 @@ const struct DenyConf* conf_get_deny_list(void)
   return denyConfList;
 }
 
+#if 0
+void conf_add_quarantine(const char *chname, const char *reason)
+{
+  struct qline *qline;
+
+  qline = (struct qline *) MyMalloc(sizeof(struct qline));
+  DupString(qline->chname, chname);
+  DupString(qline->reason, reason);
+  qline->next = GlobalQuarantineList;
+  GlobalQuarantineList = qline;
+}
+#endif
+
+const char*
+find_quarantine(const char *chname)
+{
+  struct qline *qline;
+  
+  for (qline = GlobalQuarantineList; qline; qline = qline->next)
+    if (!ircd_strcmp(qline->chname, chname))
+      return qline->reason;
+  return NULL;
+}
+
+void clear_quarantines(void)
+{
+  struct qline *qline;
+  while ((qline = GlobalQuarantineList))
+  {
+    GlobalQuarantineList = qline->next;
+    MyFree(qline->reason);
+    MyFree(qline->chname);
+    MyFree(qline);
+  }
+}
+
+
 /*
  * read_configuration_file
  *
index c45a5325917a1fb9bf532641859b7cd91192599b..a22745406dc7426ff3d9aea03bb6a1b4f55530e0 100644 (file)
@@ -205,7 +205,8 @@ static void debug_enumerator(struct Client* cptr, const char* msg)
  * different field names for "struct rusage".
  * -avalon
  */
-void send_usage(struct Client *cptr, char *nick)
+void send_usage(struct Client *cptr, struct StatDesc *sd, int stat,
+                char *param)
 {
   os_get_rusage(cptr, CurrentTime - cli_since(&me), debug_enumerator);
 
@@ -214,7 +215,8 @@ void send_usage(struct Client *cptr, char *nick)
 }
 #endif /* DEBUGMODE */
 
-void count_memory(struct Client *cptr, char *nick)
+void count_memory(struct Client *cptr, struct StatDesc *sd, int stat,
+                  char *param)
 {
   struct Client *acptr;
   struct SLink *link;
@@ -223,7 +225,8 @@ void count_memory(struct Client *cptr, char *nick)
   const struct ConnectionClass* cltmp;
   struct Membership* member;
 
-  int c = 0,                    /* clients */
+  int acc = 0,                  /* accounts */
+      c = 0,                    /* clients */
       cn = 0,                   /* connections */
       ch = 0,                   /* channels */
       lcc = 0,                  /* local client conf links */
@@ -237,7 +240,9 @@ void count_memory(struct Client *cptr, char *nick)
 
   int usi = 0,                  /* users invited */
       aw = 0,                   /* aways set */
-      wwa = 0;                  /* whowas aways */
+      wwa = 0,                  /* whowas aways */
+      gl = 0,                   /* glines */
+      ju = 0;                   /* jupes */
 
   size_t chm = 0,               /* memory used by channels */
       chbm = 0,                 /* memory used by channel bans */
@@ -246,13 +251,13 @@ void count_memory(struct Client *cptr, char *nick)
       awm = 0,                  /* memory used by aways */
       wwam = 0,                 /* whowas away memory used */
       wwm = 0,                  /* whowas array memory used */
+      glm = 0,                  /* memory used by glines */
+      jum = 0,                  /* memory used by jupes */
       com = 0,                  /* memory used by conf lines */
       dbufs_allocated = 0,      /* memory used by dbufs */
       dbufs_used = 0,           /* memory used by dbufs */
       msg_allocated = 0,       /* memory used by struct Msg */
-      msg_used = 0,            /* memory used by struct Msg */
       msgbuf_allocated = 0,    /* memory used by struct MsgBuf */
-      msgbuf_used = 0,         /* memory used by struct MsgBuf */
       rm = 0,                   /* res memory used */
       totcl = 0, totch = 0, totww = 0, tot = 0;
 
@@ -282,6 +287,9 @@ void count_memory(struct Client *cptr, char *nick)
         awm += (strlen(cli_user(acptr)->away) + 1);
       }
     }
+
+    if (IsAccount(acptr))
+      acc++;
   }
   cm = c * sizeof(struct Client);
   cnm = cn * sizeof(struct Connection);
@@ -314,7 +322,8 @@ void count_memory(struct Client *cptr, char *nick)
   send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
             ":Clients %d(%zu) Connections %d(%zu)", c, cm, cn, cnm);
   send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
-            ":Users %d(%zu) Invites %d(%zu)", us, us * sizeof(struct User),
+            ":Users %d(%zu) Accounts %d(%zu) Invites %d(%zu)",
+             us, us * sizeof(struct User), acc, acc * (ACCOUNTLEN + 1),
             usi, usi * sizeof(struct SLink));
   send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
             ":User channels %d(%zu) Aways %d(%zu)", memberships,
@@ -365,14 +374,7 @@ void count_memory(struct Client *cptr, char *nick)
             ":DBufs allocated %d(%zu) used %d(%zu)", DBufAllocCount,
             dbufs_allocated, DBufUsedCount, dbufs_used);
 
-  msgq_count_memory(&msg_allocated, &msg_used, &msgbuf_allocated,
-                   &msgbuf_used);
-  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
-            ":Msgs allocated %d(%zu) used %d(%zu)", msgCounts.alloc,
-            msg_allocated, msgCounts.used, msg_used);
-  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
-            ":MsgBufs allocated %d(%zu) used %d(%zu)", msgBufCounts.alloc,
-            msgbuf_allocated, msgBufCounts.used, msgbuf_used);
+  msgq_count_memory(cptr, &msg_allocated, &msgbuf_allocated);
 
   rm = cres_mem(cptr);
 
index 807047b921817716cb889b37da5feb9ce2de7cae..c2cbdd4b39310fb3cc0269070c6d7104f9bedfab 100644 (file)
@@ -30,7 +30,7 @@ static Numeric replyTable[] = {
 /* 000 */
   { 0 },
 /* 001 */
-  { RPL_WELCOME, ":Welcome to the Internet Relay Network %s", "001" },
+  { RPL_WELCOME, ":Welcome to the Internet Relay Network%s%s, %s", "001" },
 /* 002 */
   { RPL_YOURHOST, ":Your host is %s, running version %s", "002" },
 /* 003 */
@@ -708,7 +708,7 @@ static Numeric replyTable[] = {
 /* 337 */
   { 0 },
 /* 338 */
-  { RPL_WHOISACTUALLY, ":%s is actually %s@%s [%s]", "338" },
+  { RPL_WHOISACTUALLY, "%s %s@%s %s :Actual user@host, Actual IP", "338" },
 /* 339 */
   { 0 },
 /* 340 */
@@ -1080,7 +1080,7 @@ static Numeric replyTable[] = {
 /* 523 */
   { 0 },
 /* 524 */
-  { 0 },
+  { ERR_QUARANTINED, "%s :Channel is quarantined : %s", "524" },
 /* 525 */
   { 0 },
 /* 526 */
index 2760cad3c5b40c4e14843d72728f4f992d724903..cafbd57eb5e0aaf7b668f9e2c6ca91797005972f 100644 (file)
@@ -37,6 +37,7 @@
 #include "ircd_snprintf.h"
 #include "ircd_string.h"
 #include "list.h"
+#include "map.h"
 #include "match.h"
 #include "msg.h"
 #include "numeric.h"
@@ -47,6 +48,7 @@
 #include "s_bsd.h"
 #include "s_conf.h"
 #include "s_debug.h"
+#include "s_stats.h"
 #include "s_user.h"
 #include "send.h"
 #include "struct.h"
@@ -54,7 +56,6 @@
 #include "sys.h"
 #include "uping.h"
 #include "userload.h"
-#include "map.h"
 
 #include <assert.h>
 #include <fcntl.h>
@@ -170,7 +171,8 @@ const char* get_client_name(const struct Client* sptr, int showip)
   if (MyConnect(sptr)) {
     if (showip)
       ircd_snprintf(0, nbuf, sizeof(nbuf), "%s[%s@%s]", cli_name(sptr),
-            cli_user(sptr)->username, cli_sock_ip(sptr));
+                    IsIdented(sptr) ? cli_username(sptr) : "unknown",
+                    cli_sock_ip(sptr));
     else
         return cli_name(sptr);
     return nbuf;
@@ -390,8 +392,16 @@ int exit_client(struct Client *cptr,    /* Connection being handled by
 
   char comment1[HOSTLEN + HOSTLEN + 2];
   assert(killer);
-  if (MyConnect(victim)) {
-    cli_flags(victim) |= FLAGS_CLOSING;
+  if (MyConnect(victim))
+  {
+    SetFlag(victim, FLAG_CLOSING);
+
+    if (feature_bool(FEAT_CONNEXIT_NOTICES) && IsUser(victim))
+      sendto_opmask_butone(0, SNO_CONNEXIT,
+                           "Client exiting: %s (%s@%s) [%s] [%s]",
+                           cli_name(victim), cli_user(victim)->username,
+                           cli_user(victim)->host, comment,
+                           ircd_ntoa((const char*) &(cli_ip(victim))));
     update_load();
 
     on_for = CurrentTime - cli_firsttime(victim);
@@ -456,13 +466,15 @@ int exit_client(struct Client *cptr,    /* Connection being handled by
 
   if (IsServer(victim))
   {
-#ifdef HEAD_IN_SAND_NETSPLIT
-    strcpy(comment1, "*.net *.split");
-#else
-    strcpy(comment1, cli_name(cli_serv(victim)->up));
-    strcat(comment1, " ");
-    strcat(comment1, cli_name(victim));
-#endif
+    if (feature_bool(FEAT_HIS_NETSPLIT))
+      strcpy(comment1, "*.net *.split");
+    else
+    {
+      strcpy(comment1, cli_name(cli_serv(victim)->up));
+      strcat(comment1, " ");
+      strcat(comment1, cli_name(victim));
+    }
+
     if (IsUser(killer))
       sendto_opmask_butone(killer, SNO_OLDSNO, "%s SQUIT by %s [%s]:",
                           (cli_user(killer)->server == victim ||
@@ -477,9 +489,8 @@ int exit_client(struct Client *cptr,    /* Connection being handled by
     sendto_opmask_butone(0, SNO_NETWORK, "Net break: %C %C (%s)",
                         cli_serv(victim)->up, victim, comment);
 
-#if defined(HEAD_IN_SAND_MAP) || defined(HEAD_IN_SAND_LINKS)    
-    map_update(victim);
-#endif
+    if (feature_bool(FEAT_HIS_MAP) || feature_bool(FEAT_HIS_LINKS))
+      map_update(victim);
   }
 
   /*
@@ -487,11 +498,12 @@ int exit_client(struct Client *cptr,    /* Connection being handled by
    * except the source:
    */
   for (dlp = cli_serv(&me)->down; dlp; dlp = dlp->next) {
-    if (dlp->value.cptr != cli_from(killer) && dlp->value.cptr != victim) {
+    if (dlp->value.cptr != cli_from(killer) && dlp->value.cptr != victim)
+    {
       if (IsServer(victim))
        sendcmdto_one(killer, CMD_SQUIT, dlp->value.cptr, "%s %Tu :%s",
                      cli_name(victim), cli_serv(victim)->timestamp, comment);
-      else if (IsUser(victim) && 0 == (cli_flags(victim) & FLAGS_KILLED))
+      else if (IsUser(victim) && !HasFlag(victim, FLAG_KILLED))
        sendcmdto_one(victim, CMD_QUIT, dlp->value.cptr, ":%s", comment);
     }
   }
@@ -536,7 +548,7 @@ void initstats(void)
   memset(&ircst, 0, sizeof(ircst));
 }
 
-void tstats(struct Client *cptr, char *name)
+void tstats(struct Client *cptr, struct StatDesc *sd, int stat, char *param)
 {
   struct Client *acptr;
   int i;
index 8d9602be122bbdd4216e6f7a8900f53ba7ab8978..07e41ab3fc31f455bad41e0c5c565cdbd58f3024 100644 (file)
@@ -27,7 +27,7 @@
 #include "client.h"
 #include "hash.h"
 #include "ircd.h"
-#include "ircd_policy.h"
+#include "ircd_features.h"
 #include "ircd_snprintf.h"
 #include "numnicks.h"
 #include "send.h"
@@ -79,28 +79,17 @@ int do_numeric(int numeric, int nnn, struct Client *cptr, struct Client *sptr,
 
   ircd_snprintf(0, num, sizeof(num), "%03d", numeric);
 
-#ifdef HEAD_IN_SAND_REWRITE
   /* Since 2.10.10.pl14 we rewrite numerics from remote servers to appear to
    * come from the local server
    */
-  if (IsOper(acptr)) {
-#endif
-    if (acptr)
-      sendcmdto_one(sptr, num, num, acptr, "%C %s", acptr, parv[2]);
-    else
-      sendcmdto_channel_butone(sptr, num, num, achptr, cptr,
-                              SKIP_DEAF | SKIP_BURST, "%H %s", achptr,
-                              parv[2]);
-#ifdef HEAD_IN_SAND_REWRITE
-  } else {
-    if (acptr)
-      sendcmdto_one(&me, num, num, acptr, "%C %s", acptr, parv[2]);
-    else
-      sendcmdto_channel_butone(&me, num, num, achptr, cptr,
-                              SKIP_DEAF | SKIP_BURST, "%H %s", achptr,
-                              parv[2]);
-  }
-#endif
-
+  if (acptr)
+    sendcmdto_one((feature_bool(FEAT_HIS_REWRITE) && !IsOper(acptr)) ?
+                    &me : sptr,
+                  num, num, acptr, "%C %s", acptr, parv[2]);
+  else
+    sendcmdto_channel_butone((feature_bool(FEAT_HIS_REWRITE) && !IsOper(acptr)) ?
+                               &me : sptr,
+                             num, num, achptr, cptr, SKIP_DEAF | SKIP_BURST,
+                             "%H %s", achptr, parv[2]);
   return 0;
 }
index 4ea5094b627c2803589d27e06a33025d59b634c5..d169a697cb2aa2ceeb143b6962069ad5ae902177 100644 (file)
  */
 #include "config.h"
 
-#include "s_stats.h"
 #include "class.h"
 #include "client.h"
+#include "gline.h"
 #include "ircd.h"
 #include "ircd_chattr.h"
+#include "ircd_events.h"
+#include "ircd_features.h"
 #include "ircd_log.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "listener.h"
+#include "list.h"
 #include "match.h"
+#include "motd.h"
 #include "msg.h"
+#include "msgq.h"
 #include "numeric.h"
 #include "numnicks.h"
+#include "s_bsd.h"
 #include "s_conf.h"
+#include "s_debug.h"
+#include "s_misc.h"
+#include "s_serv.h"
+#include "s_stats.h"
 #include "s_user.h"
 #include "send.h"
 #include "struct.h"
+#include "userload.h"
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/time.h>
 
 
  *       it--not reversed as in ircd.conf!
  */
 
-/*
- *  Help info displayed when user provides no stats parameter. --Gte
- */
-const char *statsinfo[] = {
-    "The following statistics are available:",
-    "U - Service server & nick jupes information.",
-    "u - Current uptime & highest connection count.",
-    "p - Listening ports.",
-    "i - Connection authorisation lines.",
-    "y - Connection classes.",
-    "c - Remote server connection lines.",
-    "h - Hubs information.",
-    "d - Dynamic routing configuration.", 
-    "l - Current connections information.",
-    "g - Global bans (G-lines).",
-    "k - Local bans (K-Lines).",
-    "o - Operator information.", 
-    "e - Report server event loop engine.",
-    "f - Feature settings.",
-    "m - Message usage information.",
-    "t - Local connection statistics (Total SND/RCV, etc).", 
-    "v - Server list with verbose information.",
-    "w - Userload statistics.",
-    "M - Memory allocation & leak monitoring.", 
-    "z - Memory/Structure allocation information.",
-    "r - System resource usage (Debug only).", 
-    "x - List usage information (Debug only).",
-    0,
-};
-
 static unsigned int report_array[17][3] = {
   {CONF_SERVER, RPL_STATSCLINE, 'C'},
   {CONF_CLIENT, RPL_STATSILINE, 'I'},
@@ -97,14 +79,18 @@ static unsigned int report_array[17][3] = {
   {0, 0}
 };
 
-void report_configured_links(struct Client *sptr, int mask)
+static void
+stats_configured_links(struct Client *sptr, struct StatDesc* sd, int stat,
+                       char* param)
 {
   static char null[] = "<NULL>";
   struct ConfItem *tmp;
+  int mask;
   unsigned int *p;
   unsigned short int port;
   char c, *host, *pass, *name;
   
+  mask = sd->sd_funcdata;
 
   for (tmp = GlobalConfList; tmp; tmp = tmp->next) 
   {
@@ -143,36 +129,72 @@ void report_configured_links(struct Client *sptr, int mask)
   }
 }
 
-/*
- *  {CONF_TLINES, RPL_STATSTLINE, 'T'},
- *
- * see now motd_report() in motd.c
- */
-/*  void report_motd_list(struct Client* to) */
-/*  { */
-/*    const struct MotdConf* conf = conf_get_motd_list(); */
-/*    for ( ; conf; conf = conf->next) */
-/*      send_reply(to, RPL_STATSTLINE, 'T', conf->hostmask, conf->path); */
-/*  } */
-
 /*
  * {CONF_CRULEALL, RPL_STATSDLINE, 'D'},
  * {CONF_CRULEAUTO, RPL_STATSDLINE, 'd'},
  */
-void report_crule_list(struct Client* to, int mask)
+static void
+stats_crule_list(struct Client* to, struct StatDesc *sd, int stat,
+                 char *param)
 {
+  int mask;
   const struct CRuleConf* p = conf_get_crule_list();
-  for ( ; p; p = p->next) {
-    if (0 != (p->type & mask))
-      send_reply(to, RPL_STATSDLINE, (CRULE_ALL == p->type) ? 'D' : 'd', p->hostmask, p->rule);
+
+  mask = (stat == 'D') ? CRULE_ALL : CRULE_MASK;
+
+  for ( ; p; p = p->next)
+  {
+    if (p->type & mask)
+      send_reply(to, RPL_STATSDLINE, stat, p->hostmask, p->rule);
+  }
+}
+
+static void
+stats_engine(struct Client *to, struct StatDesc *sd, int stat, char *param)
+{
+  send_reply(to, RPL_STATSENGINE, engine_name());
+}
+
+static void
+stats_access(struct Client *to, struct StatDesc *sd, int stat, char *param)
+{
+  struct ConfItem *aconf;
+  int wilds = 0;
+  int count = 1000;
+
+  if (!param)
+  {
+    stats_configured_links(to, sd, stat, param);
+    return;
+  }
+
+  wilds = string_has_wildcards(param);
+
+  for (aconf = GlobalConfList; aconf; aconf = aconf->next)
+  {
+    if (aconf->status != CONF_CLIENT)
+      continue;
+    if ((!wilds && (!match(aconf->host, param) ||
+                    !match(aconf->name, param))) ||
+        (wilds && (!mmatch(param, aconf->host) ||
+                   !mmatch(param, aconf->name))))
+    {
+      send_reply(to, RPL_STATSILINE, 'I', aconf->host, aconf->name,
+                 aconf->port, get_conf_class(aconf));
+      if (--count == 0)
+        break;
+    }
   }
 }
 
+
+
 /*
  * {CONF_KILL, RPL_STATSKLINE, 'K'},
  * {CONF_IPKILL, RPL_STATSKLINE, 'k'},
  */
-void report_deny_list(struct Client* to)
+static void
+report_deny_list(struct Client* to)
 {
   const struct DenyConf* p = conf_get_deny_list();
   for ( ; p; p = p->next)
@@ -180,67 +202,322 @@ void report_deny_list(struct Client* to)
                p->hostmask, p->message, p->usermask);
 }
 
-/* m_stats is so obnoxiously full of special cases that the different
- * hunt_server() possiblites were becoming very messy. It now uses a
- * switch() so as to be easier to read and update as params change. 
- * -Ghostwolf 
- *
- * 2.10.11: Don't check for the oper limitation if it's not our local server.
- *          thusly once all the hubs have upgraded local opers will be able
- *          to remote stats anywhere on the network.
- */
-int hunt_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[], char stat, int MustBeOper)
+static void
+stats_klines(struct Client *sptr, struct StatDesc *sd, int stat, char *mask)
 {
-  switch (stat)
+  int wilds = 0;
+  int count = 3;
+  int limit_query = 0;
+  char *user  = 0;
+  char *host;
+  const struct DenyConf* conf;
+  if (!IsAnOper(sptr))
+    limit_query = 1;
+  
+  if (!mask)
+  {
+    if (limit_query)
+      need_more_params(sptr, "STATS K");
+    else
+      report_deny_list(sptr);
+    return;
+  }
+
+  if (!limit_query)
+  {
+    wilds = string_has_wildcards(mask);
+    count = 1000;
+  }
+  if ((host = strchr(mask, '@')))
   {
-      /* open to all, standard # of params */
-    case 'U':
-    case 'u':
-    case 'F':
-    case 'f':
-      return hunt_server_cmd(sptr, CMD_STATS, cptr, MustBeOper, "%s :%C", 2,
-                            parc, parv);
-
-    /* open to all, varying # of params */
-    case 'k':
-    case 'K':
-    case 'i':
-    case 'I':
-    case 'p':
-    case 'P':
+    user = mask;
+    *host++ = '\0';
+  }
+  else
+    host = mask;
+
+  for (conf = conf_get_deny_list(); conf; conf = conf->next)
+  {
+    if ((!wilds && ((user || conf->hostmask) &&
+                    !match(conf->hostmask, host) &&
+                    (!user || !match(conf->usermask, user)))) ||
+        (wilds && !mmatch(host, conf->hostmask) &&
+         (!user || !mmatch(user, conf->usermask))))
     {
-      if (parc > 3)
-       return hunt_server_cmd(sptr, CMD_STATS, cptr, MustBeOper, "%s %C :%s",
-                              2, parc, parv);
-      else
-       return hunt_server_cmd(sptr, CMD_STATS, cptr, MustBeOper, "%s :%C", 2,
-                              parc, parv);
+      send_reply(sptr, RPL_STATSKLINE,
+                 (conf->flags & DENY_FLAGS_IP) ? 'k' : 'K',
+                 conf->hostmask, conf->message, conf->usermask);
+      if (--count == 0)
+        return;
     }
+  }
+}
+
+static void
+stats_links(struct Client* sptr, struct StatDesc* sd, int stat, char* name)
+{
+  struct Client *acptr;
+  int i;
+  int wilds = 0;
 
-      /* oper only, varying # of params */
-    case 'l':
-    case 'L':
-    case 'M':
+  if (name)
+    wilds = string_has_wildcards(name);
+
+  /*
+   * Send info about connections which match, or all if the
+   * mask matches me.name.  Only restrictions are on those who
+   * are invisible not being visible to 'foreigners' who use
+   * a wild card based search to list it.
+   */
+  send_reply(sptr, SND_EXPLICIT | RPL_STATSLINKINFO, "Connection SendQ "
+             "SendM SendKBytes RcveM RcveKBytes :Open since");
+    for (i = 0; i <= HighestFd; i++)
     {
-      if (parc == 4)
-       return hunt_server_cmd(sptr, CMD_STATS, cptr,
-                              MyUser(sptr) ? 1 : MustBeOper, "%s %C :%s", 2,
-                              parc, parv);
-      else if (parc > 4)
-       return hunt_server_cmd(sptr, CMD_STATS, cptr,
-                              MyUser(sptr) ? 1 : MustBeOper, "%s %C %s :%s",
-                              2, parc, parv);
-      else 
-       return hunt_server_cmd(sptr, CMD_STATS, cptr,
-                              MyUser(sptr) ? 1 : MustBeOper, "%s :%C", 2,
-                              parc, parv);
+      if (!(acptr = LocalClientArray[i]))
+        continue;
+      /* Don't return clients when this is a request for `all' */
+      if (!name && IsUser(acptr))
+        continue;
+      /* Don't show invisible people to non opers unless they know the nick */
+      if (IsInvisible(acptr) && (!name || wilds) && !IsAnOper(acptr) &&
+          (acptr != sptr))
+        continue;
+      /* Only show the ones that match the given mask - if any */
+      if (name && wilds && match(name, cli_name(acptr)))
+        continue;
+      /* Skip all that do not match the specific query */
+      if (!(!name || wilds) && 0 != ircd_strcmp(name, cli_name(acptr)))
+        continue;
+      send_reply(sptr, SND_EXPLICIT | RPL_STATSLINKINFO,
+                 "%s %u %u %u %u %u :%Tu",
+                 (*(cli_name(acptr))) ? cli_name(acptr) : "<unregistered>",
+                 (int)MsgQLength(&(cli_sendQ(acptr))), (int)cli_sendM(acptr),
+                 (int)cli_sendK(acptr), (int)cli_receiveM(acptr),
+                 (int)cli_receiveK(acptr), CurrentTime - cli_firsttime(acptr));
     }
+}
+
+static void
+stats_commands(struct Client* to, struct StatDesc* sd, int stat, char* param)
+{
+  struct Message *mptr;
+
+  for (mptr = msgtab; mptr->cmd; mptr++)
+    if (mptr->count)
+      send_reply(to, RPL_STATSCOMMANDS, mptr->cmd, mptr->count, mptr->bytes);
+}
+
+static void
+stats_quarantine(struct Client* to, struct StatDesc* sd, int stat, char* param)
+{
+  struct qline *qline;
+
+  for (qline = GlobalQuarantineList; qline; qline = qline->next)
+  {
+    if (param && match(param, qline->chname)) /* narrow search */
+      continue;
+    send_reply(to, RPL_STATSQLINE, qline->chname, qline->reason);
+   }
+ }
+static void
+stats_uptime(struct Client* to, struct StatDesc* sd, int stat, char* param)
+{
+  time_t nowr;
+
+  nowr = CurrentTime - cli_since(&me);
+  send_reply(to, RPL_STATSUPTIME, nowr / 86400, (nowr / 3600) % 24,
+             (nowr / 60) % 60, nowr % 60);
+  send_reply(to, RPL_STATSCONN, max_connection_count, max_client_count);
+}
+
+static void
+stats_servers_verbose(struct Client* sptr, struct StatDesc* sd, int stat,
+                     char* param)
+{
+  struct Client *acptr;
+  
+  /*
+   * lowercase 'v' is for human-readable,
+   * uppercase 'V' is for machine-readable
+   */
+  if (stat == 'v')
+    send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE,
+               "%-20s %-20s Flags Hops Numeric   Lag  RTT   Up Down "
+               "Clients/Max Proto %-10s :Info", "Servername", "Uplink",
+               "LinkTS");
 
-      /* oper only, standard # of params */
-    default:
-      return hunt_server_cmd(sptr, CMD_STATS, cptr,
-                            MyUser(sptr) ? 1 : MustBeOper, "%s :%C", 2, parc,
-                            parv);
+  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr))
+  {
+    if (!IsServer(acptr) && !IsMe(acptr))
+      continue;
+    /* narrow search */
+    if (param && match(param, cli_name(acptr)))
+      continue;
+    send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE, stat == 'v' ?
+               "%-20s %-20s %c%c%c%c  %4i %s %-4i %5i %4i %4i %4i %5i %5i "
+               "P%-2i   %Tu :%s" :
+               "%s %s %c%c%c%c %i %s %i %i %i %i %i %i %i P%i %Tu :%s",
+               cli_name(acptr),
+               cli_name(cli_serv(acptr)->up),
+               IsBurst(acptr) ? 'B' : '-',
+               IsBurstAck(acptr) ? 'A' : '-',
+               IsHub(acptr) ? 'H' : '-',
+               IsService(acptr) ? 'S' : '-',
+               cli_hopcount(acptr),
+               NumServ(acptr),
+               base64toint(cli_yxx(acptr)),
+               cli_serv(acptr)->lag,
+               cli_serv(acptr)->asll_rtt,
+               cli_serv(acptr)->asll_to,
+               cli_serv(acptr)->asll_from,
+               cli_serv(acptr)->clients,
+               cli_serv(acptr)->nn_mask,
+               cli_serv(acptr)->prot,
+               cli_serv(acptr)->timestamp,
+               cli_info(acptr));
   }
 }
 
+#ifdef DEBUGMODE
+static void
+stats_meminfo(struct Client* to, struct StatDesc* sd, int stat, char* param)
+{
+  class_send_meminfo(to);
+  send_listinfo(to, 0);
+}
+#endif
+
+static void
+stats_help(struct Client* to, struct StatDesc* sd, int stat, char* param)
+{
+  struct StatDesc *asd;
+
+  /* only if it's my user */
+  if (MyUser(to))
+    for (asd = statsinfo; asd->sd_c; asd++)
+      if (asd->sd_c != sd->sd_c) /* don't send the help for us */
+        sendcmdto_one(&me, CMD_NOTICE, to, "%C :%c - %s", to, asd->sd_c,
+                      asd->sd_desc);
+}
+
+/* This array of structures contains information about all single-character
+ * stats.  Struct StatDesc is defined in s_stats.h.
+ */
+struct StatDesc statsinfo[] = {
+  { 'c', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_c,
+    stats_configured_links, CONF_SERVER,
+    "Remote server connection lines." },
+  { 'd', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_d,
+    stats_crule_list, 0,
+    "Dynamic routing configuration." },
+  { 'e', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_e,
+    stats_engine, 0,
+    "Report server event loop engine." },
+  { 'f', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_f,
+    feature_report, 0,
+    "Feature settings." },
+  { 'g', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_g,
+    gline_stats, 0,
+    "Global bans (G-lines)." },
+  { 'h', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_h,
+    stats_configured_links, (CONF_HUB | CONF_LEAF),
+    "Hubs information." },
+  { 'i', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_i,
+    stats_access, CONF_CLIENT,
+    "Connection authorization lines." },
+  { 'j', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_j,
+    msgq_histogram, 0,
+    "Message length histogram." },
+  { 'k', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_k,
+    stats_klines, 0,
+    "Local bans (K-Lines)." },
+  { 'l', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_l,
+    stats_links, 0,
+    "Current connections information." },
+#if 0
+  { 'M', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_M,
+    stats_memtotal, 0,
+    "Memory allocation & leak monitoring." },
+#endif
+  { 'm', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_m,
+    stats_commands, 0,
+    "Message usage information." },
+  { 'o', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_o,
+    stats_configured_links, CONF_OPS,
+    "Operator information." },
+  { 'p', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_p,
+    show_ports, 0,
+    "Listening ports." },
+  { 'q', (STAT_FLAG_OPERONLY | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_q,
+    stats_quarantine, 0,
+    "Quarantined channels list." },
+#ifdef DEBUGMODE
+  { 'r', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_r,
+    send_usage, 0,
+    "System resource usage (Debug only)." },
+#endif
+  { 'T', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_T,
+    motd_report, 0,
+    "Configured Message Of The Day files." },
+  { 't', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_t,
+    tstats, 0,
+    "Local connection statistics (Total SND/RCV, etc)." },
+  { 'U', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_U,
+    stats_configured_links, CONF_UWORLD,
+    "Service server & nick jupes information." },
+  { 'u', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_u,
+    stats_uptime, 0,
+    "Current uptime & highest connection count." },
+  { 'v', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_v,
+    stats_servers_verbose, 0,
+    "Verbose server information." },
+  { 'w', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_w,
+    calc_load, 0,
+    "Userload statistics." },
+#ifdef DEBUGMODE
+  { 'x', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_x,
+    stats_meminfo, 0,
+    "List usage information (Debug only)." },
+#endif
+  { 'y', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_y,
+    report_classes, 0,
+    "Connection classes." },
+  { 'z', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_z,
+    count_memory, 0,
+    "Memory/Structure allocation information." },
+  { '*', (STAT_FLAG_CASESENS | STAT_FLAG_VARPARAM), FEAT_LAST_F,
+    stats_help, 0,
+    "Send help for stats." },
+  { '\0', 0, FEAT_LAST_F, 0, 0, 0 }
+};
+
+/* This array is for mapping from characters to statistics descriptors */
+struct StatDesc *statsmap[256];
+
+/* Function to build the statsmap from the statsinfo array */
+void
+stats_init(void)
+{
+  struct StatDesc *sd;
+  int i;
+
+  /* Make darn sure the statsmap array is initialized to all zeros */
+  for (i = 1; i < 256; i++)
+    statsmap[i] = 0;
+
+  /* Build the mapping */
+  for (sd = statsinfo; sd->sd_c; sd++)
+  {
+    if (sd->sd_flags & STAT_FLAG_CASESENS)
+      /* case sensitive character... */
+      statsmap[(int)sd->sd_c] = sd;
+    else
+    {
+      /* case insensitive--make sure to put in two entries */
+      statsmap[(int)ToLower((int)sd->sd_c)] = sd;
+      statsmap[(int)ToUpper((int)sd->sd_c)] = sd;
+    }
+  }
+}
index dd6b51b349f435df245b9c66db2196f649cd34d3..9ad2b2e90c3c7c12cc8b247031454b6cc2c58334 100644 (file)
@@ -35,7 +35,6 @@
 #include "ircd_chattr.h"
 #include "ircd_features.h"
 #include "ircd_log.h"
-#include "ircd_policy.h"
 #include "ircd_reply.h"
 #include "ircd_snprintf.h"
 #include "ircd_string.h"
@@ -229,7 +228,7 @@ int hunt_server_cmd(struct Client *from, const char *cmd, const char *tok,
     return HUNTED_NOSUCH;
   }
 
-  assert(!IsServer(from));
+  /* assert(!IsServer(from)); */
 
   parv[server] = (char *) acptr; /* HACK! HACK! HACK! ARGH! */
 
@@ -287,37 +286,6 @@ int hunt_server_prio_cmd(struct Client *from, const char *cmd, const char *tok,
   return (HUNTED_PASS);
 }
 
-/*
- * 'do_nick_name' ensures that the given parameter (nick) is really a proper
- * string for a nickname (note, the 'nick' may be modified in the process...)
- *
- * RETURNS the length of the final NICKNAME (0, if nickname is invalid)
- *
- * Nickname characters are in range 'A'..'}', '_', '-', '0'..'9'
- *  anything outside the above set will terminate nickname.
- * In addition, the first character cannot be '-' or a Digit.
- *
- * Note:
- *  The '~'-character should be allowed, but a change should be global,
- *  some confusion would result if only few servers allowed it...
- */
-int do_nick_name(char* nick)
-{
-  char* ch  = nick;
-  char* end = ch + NICKLEN;
-  assert(0 != ch);
-
-  if (*ch == '-' || IsDigit(*ch))        /* first character in [0..9-] */
-    return 0;
-
-  for ( ; (ch < end) && *ch; ++ch)
-    if (!IsNickChar(*ch))
-      break;
-
-  *ch = '\0';
-
-  return (ch - nick);
-}
 
 /*
  * clean_user_id
@@ -394,6 +362,7 @@ int register_user(struct Client *cptr, struct Client *sptr,
   short            badid = 0;
   short            digitgroups = 0;
   struct User*     user = cli_user(sptr);
+  struct Flags flag;
   char             ip_base64[8];
 
   user->last = CurrentTime;
@@ -452,8 +421,8 @@ int register_user(struct Client *cptr, struct Client *sptr,
     aconf = cli_confs(sptr)->value.aconf;
 
     clean_user_id(user->username,
-        (cli_flags(sptr) & FLAGS_GOTID) ? cli_username(sptr) : username,
-        (cli_flags(sptr) & FLAGS_DOID) && !(cli_flags(sptr) & FLAGS_GOTID));
+                  HasFlag(sptr, FLAG_GOTID) ? cli_username(sptr) : username,
+                  HasFlag(sptr, FLAG_DOID) && !HasFlag(sptr, FLAG_GOTID));
 
     if ((user->username[0] == '\0')
         || ((user->username[0] == '~') && (user->username[1] == '\000')))
@@ -541,7 +510,7 @@ int register_user(struct Client *cptr, struct Client *sptr,
       else if ((!lower && !upper) || !IsAlnum(c))
         badid = 1;
     }
-    if (badid && (!(cli_flags(sptr) & FLAGS_GOTID) ||
+    if (badid && (!HasFlag(sptr, FLAG_GOTID) ||
         strcmp(cli_username(sptr), username) != 0))
     {
       ServerStats->is_ref++;
@@ -572,7 +541,11 @@ int register_user(struct Client *cptr, struct Client *sptr,
     cli_handler(sptr) = CLIENT_HANDLER;
     release_dns_reply(sptr);
 
-    send_reply(sptr, RPL_WELCOME, nick);
+    send_reply(sptr,
+               RPL_WELCOME,
+               feature_str(FEAT_PROVIDER) ? " via " : "",
+               feature_str(FEAT_PROVIDER) ? feature_str(FEAT_PROVIDER) : "",
+               nick);
     /*
      * This is a duplicate of the NOTICE but see below...
      */
@@ -586,6 +559,12 @@ int register_user(struct Client *cptr, struct Client *sptr,
 /*      nextping = CurrentTime; */
     if (cli_snomask(sptr) & SNO_NOISY)
       set_snomask(sptr, cli_snomask(sptr) & SNO_NOISY, SNO_ADD);
+    if (feature_bool(FEAT_CONNEXIT_NOTICES))
+      sendto_opmask_butone(0, SNO_CONNEXIT,
+                           "Client connecting: %s (%s@%s) [%s] {%d}",
+                           cli_name(sptr), user->username, user->host,
+                           cli_sock_ip(sptr), get_client_class(sptr));
+
     IPcheck_connect_succeeded(sptr);
   }
   else
@@ -599,11 +578,11 @@ int register_user(struct Client *cptr, struct Client *sptr,
       sendcmdto_one(&me, CMD_KILL, cptr, "%C :%s (%s != %s[%s])",
                     sptr, cli_name(&me), cli_name(user->server), cli_name(cli_from(acptr)),
                     cli_sockhost(cli_from(acptr)));
-      cli_flags(sptr) |= FLAGS_KILLED;
+      SetFlag(sptr, FLAG_KILLED);
       return exit_client(cptr, sptr, &me, "NICK server wrong direction");
     }
-    else
-      cli_flags(sptr) |= (cli_flags(acptr) & FLAGS_TS8);
+    else if (HasFlag(acptr, FLAG_TS8))
+      SetFlag(sptr, FLAG_TS8);
 
     /*
      * Check to see if this user is being propogated
@@ -611,11 +590,13 @@ int register_user(struct Client *cptr, struct Client *sptr,
      * FIXME: This can be speeded up - its stupid to check it for
      * every NICK message in a burst again  --Run.
      */
-    for (acptr = user->server; acptr != &me; acptr = cli_serv(acptr)->up) {
+    for (acptr = user->server; acptr != &me; acptr = cli_serv(acptr)->up)
+    {
       if (IsBurst(acptr) || Protocol(acptr) < 10)
         break;
     }
-    if (!IPcheck_remote_connect(sptr, (acptr != &me))) {
+    if (!IPcheck_remote_connect(sptr, (acptr != &me)))
+    {
       /*
        * We ran out of bits to count this
        */
@@ -636,8 +617,8 @@ int register_user(struct Client *cptr, struct Client *sptr,
   /* Send umode to client */
   if (MyUser(sptr))
   {
-    send_umode(cptr, sptr, 0, ALL_UMODES);
-    if (cli_snomask(sptr) != SNO_DEFAULT && (cli_flags(sptr) & FLAGS_SERVNOTICE))
+    send_umode(cptr, sptr, &flag, ALL_UMODES);
+    if (cli_snomask(sptr) != SNO_DEFAULT && HasFlag(sptr, FLAG_SERVNOTICE))
       send_reply(sptr, RPL_SNOMASK, cli_snomask(sptr), cli_snomask(sptr));
   }
 
@@ -649,16 +630,16 @@ static const struct UserMode {
   unsigned int flag;
   char         c;
 } userModeList[] = {
-  { FLAGS_OPER,        'o' },
-  { FLAGS_LOCOP,       'O' },
-  { FLAGS_INVISIBLE,   'i' },
-  { FLAGS_WALLOP,      'w' },
-  { FLAGS_SERVNOTICE,  's' },
-  { FLAGS_DEAF,        'd' },
-  { FLAGS_CHSERV,      'k' },
-  { FLAGS_DEBUG,       'g' },
-  { FLAGS_ACCOUNT,     'r' },
-  { FLAGS_HIDDENHOST,  'x' }
+  { FLAG_OPER,        'o' },
+  { FLAG_LOCOP,       'O' },
+  { FLAG_INVISIBLE,   'i' },
+  { FLAG_WALLOP,      'w' },
+  { FLAG_SERVNOTICE,  's' },
+  { FLAG_DEAF,        'd' },
+  { FLAG_CHSERV,      'k' },
+  { FLAG_DEBUG,       'g' },
+  { FLAG_ACCOUNT,     'r' },
+  { FLAG_HIDDENHOST,  'x' }
 };
 
 #define USERMODELIST_SIZE sizeof(userModeList) / sizeof(struct UserMode)
@@ -684,12 +665,16 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
 
     cli_hopcount(new_client) = atoi(parv[2]);
     cli_lastnick(new_client) = atoi(parv[3]);
-    if (Protocol(cptr) > 9 && parc > 7 && *parv[6] == '+') {
-      for (p = parv[6] + 1; *p; p++) {
-        for (i = 0; i < USERMODELIST_SIZE; ++i) {
-          if (userModeList[i].c == *p) {
-            cli_flags(new_client) |= userModeList[i].flag;
-           if (userModeList[i].flag & FLAGS_ACCOUNT)
+    if (Protocol(cptr) > 9 && parc > 7 && *parv[6] == '+')
+    {
+      for (p = parv[6] + 1; *p; p++)
+      {
+        for (i = 0; i < USERMODELIST_SIZE; ++i)
+        {
+          if (userModeList[i].c == *p)
+          {
+            SetFlag(new_client, userModeList[i].flag);
+           if (userModeList[i].flag == FLAG_ACCOUNT)
              account = parv[7];
             break;
           }
@@ -747,7 +732,8 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
        * however, allow to do two nick changes immediately after another
        * before limiting the nick flood. -Run
        */
-      if (CurrentTime < cli_nextnick(cptr)) {
+      if (CurrentTime < cli_nextnick(cptr))
+      {
         cli_nextnick(cptr) += 2;
         send_reply(cptr, ERR_NICKTOOFAST, parv[1],
                    cli_nextnick(cptr) - CurrentTime);
@@ -840,7 +826,8 @@ static unsigned char hash_target(unsigned int target)
  *
  * Cannonifies target for client `sptr'.
  */
-void add_target(struct Client *sptr, void *target)
+void
+add_target(struct Client *sptr, void *target)
 {
   /* Ok, this shouldn't work esp on alpha
   */
@@ -851,6 +838,9 @@ void add_target(struct Client *sptr, void *target)
   assert(cli_local(sptr));
 
   targets = cli_targets(sptr);
+
+  if (IsChannelName(cli_name(sptr)) && IsInvited(sptr, target))
+    return;
   /* 
    * Already in table?
    */
@@ -1000,15 +990,16 @@ int whisper(struct Client* source, const char* nick, const char* channel,
 /*
  * added Sat Jul 25 07:30:42 EST 1992
  */
-void send_umode_out(struct Client *cptr, struct Client *sptr, int old,
-                   int prop)
+void send_umode_out(struct Client *cptr, struct Client *sptr,
+                    struct Flags *old, int prop)
 {
   int i;
   struct Client *acptr;
 
-  send_umode(NULL, sptr, old, SEND_UMODES & ~(prop ? 0 : FLAGS_OPER));
+  send_umode(NULL, sptr, old, prop ? SEND_UMODES : SEND_UMODES_BUT_OPER);
 
-  for (i = HighestFd; i >= 0; i--) {
+  for (i = HighestFd; i >= 0; i--)
+  {
     if ((acptr = LocalClientArray[i]) && IsServer(acptr) &&
         (acptr != cptr) && (acptr != sptr) && *umodeBuf)
       sendcmdto_one(sptr, CMD_MODE, acptr, "%s :%s", cli_name(sptr), umodeBuf);
@@ -1058,45 +1049,42 @@ void send_user_info(struct Client* sptr, char* names, int rpl, InfoFormatter fmt
  * set, its hostmask is changed.
  */
 #define FLAGS_HOST_HIDDEN      (FLAGS_ACCOUNT|FLAGS_HIDDENHOST)
-int hide_hostmask(struct Client *cptr, unsigned int flags)
+int
+hide_hostmask(struct Client *cptr, unsigned int flag)
 {
   struct Membership *chan;
-  int newflags;
-
-  if (MyConnect(cptr) && !feature_bool(FEAT_HOST_HIDING))
-    flags &= ~FLAGS_HIDDENHOST;
-    
-  newflags = cli_flags(cptr) | flags;
-  if ((newflags & FLAGS_HOST_HIDDEN) != FLAGS_HOST_HIDDEN) {
-    /* The user doesn't have both flags, don't change the hostmask */
-    cli_flags(cptr) |= flags;
+
+  if (MyConnect(cptr) && !feature_bool(FEAT_HOST_HIDING) &&
+      flag == FLAG_HIDDENHOST)
+    return 0;
+
+  SetFlag(cptr, flag);
+  if (!HasFlag(cptr, FLAG_HIDDENHOST) || !HasFlag(cptr, FLAG_ACCOUNT))
     return 0;
-  }
 
   sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Registered");
   ircd_snprintf(0, cli_user(cptr)->host, HOSTLEN, "%s.%s",
-    cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST));
-  cli_flags(cptr) |= flags;
+                cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST));
 
   /*
    * Go through all channels the client was on, rejoin him
    * and set the modes, if any
    */
-  for (chan = cli_user(cptr)->channel; chan; chan = chan->next_channel) {
+  for (chan = cli_user(cptr)->channel; chan; chan = chan->next_channel)
+  {
     sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr,
-      "%H", chan->channel);
-    if (IsChanOp(chan) && HasVoice(chan)) {
+                                     "%H", chan->channel);
+    if (IsChanOp(chan) && HasVoice(chan))
       sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr,
-        "%H +ov %C %C", chan->channel, cptr, cptr);
-    } else if (IsChanOp(chan) || HasVoice(chan)) {
+                                       "%H +ov %C %C", chan->channel, cptr,
+                                       cptr);
+    else if (IsChanOp(chan) || HasVoice(chan))
       sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr,
         "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', cptr);
-    }
   }
   return 0;
 }
 
-
 /*
  * set_user_mode() added 15/10/91 By Darren Reed.
  *
@@ -1111,7 +1099,7 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
   struct Client *acptr;
   int what;
   int i;
-  int setflags;
+  struct Flags setflags;
   unsigned int tmpmask = 0;
   int snomask_given = 0;
   char buf[BUFSIZE];
@@ -1145,14 +1133,15 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
   {
     m = buf;
     *m++ = '+';
-    for (i = 0; i < USERMODELIST_SIZE; ++i) {
-      if ((userModeList[i].flag & cli_flags(sptr)) &&
-         !(userModeList[i].flag & FLAGS_ACCOUNT))
+    for (i = 0; i < USERMODELIST_SIZE; i++)
+    {
+      if (HasFlag(sptr, userModeList[i].flag) &&
+          userModeList[i].flag != FLAG_ACCOUNT)
         *m++ = userModeList[i].c;
     }
     *m = '\0';
     send_reply(sptr, RPL_UMODEIS, buf);
-    if ((cli_flags(sptr) & FLAGS_SERVNOTICE) && MyConnect(sptr)
+    if (HasFlag(sptr, FLAG_SERVNOTICE) && MyConnect(sptr)
         && cli_snomask(sptr) !=
         (unsigned int)(IsOper(sptr) ? SNO_OPERDEFAULT : SNO_DEFAULT))
       send_reply(sptr, RPL_SNOMASK, cli_snomask(sptr), cli_snomask(sptr));
@@ -1204,8 +1193,10 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
         if (what == MODE_ADD)
           SetOper(sptr);
         else {
-          cli_flags(sptr) &= ~(FLAGS_OPER | FLAGS_LOCOP);
-          if (MyConnect(sptr)) {
+          ClrFlag(sptr, FLAG_OPER);
+          ClrFlag(sptr, FLAG_LOCOP);
+          if (MyConnect(sptr))
+          {
             tmpmask = cli_snomask(sptr) & ~SNO_OPER;
             cli_handler(sptr) = CLIENT_HANDLER;
           }
@@ -1214,9 +1205,12 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
       case 'O':
         if (what == MODE_ADD)
           SetLocOp(sptr);
-        else { 
-          cli_flags(sptr) &= ~(FLAGS_OPER | FLAGS_LOCOP);
-          if (MyConnect(sptr)) {
+        else
+        { 
+          ClrFlag(sptr, FLAG_OPER);
+          ClrFlag(sptr, FLAG_LOCOP);
+          if (MyConnect(sptr))
+          {
             tmpmask = cli_snomask(sptr) & ~SNO_OPER;
             cli_handler(sptr) = CLIENT_HANDLER;
           }
@@ -1259,67 +1253,75 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
    * Evaluate rules for new user mode
    * Stop users making themselves operators too easily:
    */
-  if (!IsServer(cptr)) {
-    if (!(setflags & FLAGS_OPER) && IsOper(sptr))
+  if (!IsServer(cptr))
+  {
+    if (!FlagHas(&setflags, FLAG_OPER) && IsOper(sptr))
       ClearOper(sptr);
-    if (!(setflags & FLAGS_LOCOP) && IsLocOp(sptr))
+    if (!FlagHas(&setflags, FLAG_LOCOP) && IsLocOp(sptr))
       ClearLocOp(sptr);
     /*
      * new umode; servers can set it, local users cannot;
      * prevents users from /kick'ing or /mode -o'ing
      */
-    if (!(setflags & FLAGS_CHSERV))
+    if (!FlagHas(&setflags, FLAG_CHSERV))
       ClearChannelService(sptr);
     /*
      * only send wallops to opers
      */
     if (feature_bool(FEAT_WALLOPS_OPER_ONLY) && !IsAnOper(sptr) &&
-       !(setflags & FLAGS_WALLOP))
+       !FlagHas(&setflags, FLAG_WALLOP))
       ClearWallops(sptr);
-#ifdef SERVNOTICE_OPER_ONLY
-    if (MyConnect(sptr) && !IsAnOper(sptr) && !(setflags & FLAGS_SERVNOTICE)) {
+    if (feature_bool(FEAT_HIS_SNOTICES_OPER_ONLY) && MyConnect(sptr) &&
+        !IsAnOper(sptr) && !FlagHas(&setflags, FLAG_SERVNOTICE))
+    {
       ClearServNotice(sptr);
       set_snomask(sptr, 0, SNO_SET);
     }
-#endif
-#ifdef DEBUG_OPER_ONLY
-    if (!IsAnOper(sptr) && !(setflags & FLAGS_DEBUG))
+    if (feature_bool(FEAT_HIS_DEBUG_OPER_ONLY) &&
+        !IsAnOper(sptr) && !FlagHas(&setflags, FLAG_DEBUG))
       ClearDebug(sptr);
-#endif
   }
-  if (MyConnect(sptr)) {
-    if ((setflags & (FLAGS_OPER | FLAGS_LOCOP)) && !IsAnOper(sptr))
+  if (MyConnect(sptr))
+  {
+    if (FlagHas(&setflags, FLAG_OPER) || FlagHas(&setflags, FLAG_LOCOP))
       det_confs_butmask(sptr, CONF_CLIENT & ~CONF_OPS);
 
-    if (SendServNotice(sptr)) {
+    if (SendServNotice(sptr))
+    {
       if (tmpmask != cli_snomask(sptr))
        set_snomask(sptr, tmpmask, SNO_SET);
       if (cli_snomask(sptr) && snomask_given)
        send_reply(sptr, RPL_SNOMASK, cli_snomask(sptr), cli_snomask(sptr));
-    } else
+    }
+    else
       set_snomask(sptr, 0, SNO_SET);
   }
   /*
    * Compare new flags with old flags and send string which
    * will cause servers to update correctly.
    */
-  if (!(setflags & FLAGS_OPER) && IsOper(sptr)) { /* user now oper */
+  if (!FlagHas(&setflags, FLAG_OPER) && IsOper(sptr))
+  {
+    /* user now oper */
     ++UserStats.opers;
     client_set_privs(sptr, NULL);
   }
-  if (HasPriv(sptr, PRIV_PROPAGATE)) /* remember propagate privilege setting */
+  /* remember propagate privilege setting */
+  if (HasPriv(sptr, PRIV_PROPAGATE))
     prop = 1;
-  if ((setflags & FLAGS_OPER) && !IsOper(sptr)) { /* user no longer oper */
+  if (FlagHas(&setflags, FLAG_OPER) && !IsOper(sptr))
+  {
+    /* user no longer oper */
     --UserStats.opers;
     client_set_privs(sptr, NULL); /* will clear propagate privilege */
   }
-  if ((setflags & FLAGS_INVISIBLE) && !IsInvisible(sptr))
+  if (FlagHas(&setflags, FLAG_INVISIBLE) && !IsInvisible(sptr))
     --UserStats.inv_clients;
-  if (!(setflags & FLAGS_INVISIBLE) && IsInvisible(sptr))
+  if (!FlagHas(&setflags, FLAG_INVISIBLE) && IsInvisible(sptr))
     ++UserStats.inv_clients;
-  if (!(setflags & FLAGS_HIDDENHOST) && do_host_hiding)
-    hide_hostmask(sptr, FLAGS_HIDDENHOST);
-  send_umode_out(cptr, sptr, setflags, prop);
+  if (!FlagHas(&setflags, FLAG_HIDDENHOST) && do_host_hiding)
+    hide_hostmask(sptr, FLAG_HIDDENHOST);
+  send_umode_out(cptr, sptr, &setflags, prop);
 
   return 0;
 }
@@ -1330,22 +1332,25 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
  */
 char *umode_str(struct Client *cptr)
 {
-  char* m = umodeBuf;                /* Maximum string size: "owidg\0" */
-  int   i;
-  int   c_flags;
+  /* Maximum string size: "owidgrx\0" */
+  char *m = umodeBuf;
+  int i;
+  struct Flags c_flags;
 
-  c_flags = cli_flags(cptr) & SEND_UMODES; /* cleaning up the original code */
   if (HasPriv(cptr, PRIV_PROPAGATE))
-    c_flags |= FLAGS_OPER;
+    FlagSet(&c_flags, FLAG_OPER);
   else
-    c_flags &= ~FLAGS_OPER;
+    FlagClr(&c_flags, FLAG_OPER);
 
-  for (i = 0; i < USERMODELIST_SIZE; ++i) {
-    if ( (c_flags & userModeList[i].flag))
+  for (i = 0; i < USERMODELIST_SIZE; ++i)
+  {
+    if (FlagHas(&c_flags, userModeList[i].flag) &&
+        userModeList[i].flag >= FLAG_GLOBAL_UMODES)
       *m++ = userModeList[i].c;
   }
 
-  if (IsAccount(cptr)) {
+  if (IsAccount(cptr))
+  {
     char* t = cli_user(cptr)->account;
 
     *m++ = ' ';
@@ -1363,7 +1368,8 @@ char *umode_str(struct Client *cptr)
  * Send the MODE string for user (user) to connection cptr
  * -avalon
  */
-void send_umode(struct Client *cptr, struct Client *sptr, int old, int sendmask)
+void send_umode(struct Client *cptr, struct Client *sptr, struct Flags *old,
+                int sendset)
 {
   int i;
   int flag;
@@ -1372,15 +1378,31 @@ void send_umode(struct Client *cptr, struct Client *sptr, int old, int sendmask)
 
   /*
    * Build a string in umodeBuf to represent the change in the user's
-   * mode between the new (sptr->flag) and 'old'.
+   * mode between the new (cli_flags(sptr)) and 'old', but skipping
+   * the modes indicated by sendset.
    */
   m = umodeBuf;
   *m = '\0';
-  for (i = 0; i < USERMODELIST_SIZE; ++i) {
+  for (i = 0; i < USERMODELIST_SIZE; ++i)
+  {
     flag = userModeList[i].flag;
-    if (MyUser(sptr) && !(flag & sendmask))
+    if (FlagHas(old, flag)
+        == HasFlag(sptr, flag))
       continue;
-    if ( (flag & old) && !(cli_flags(sptr) & flag))
+    switch (sendset)
+    {
+    case ALL_UMODES:
+      break;
+    case SEND_UMODES_BUT_OPER:
+      if (flag == FLAG_OPER)
+        continue;
+      /* and fall through */
+    case SEND_UMODES:
+      if (flag < FLAG_GLOBAL_UMODES)
+        continue;
+      break;      
+    }
+    if (FlagHas(old, flag))
     {
       if (what == MODE_DEL)
         *m++ = userModeList[i].c;
@@ -1391,7 +1413,7 @@ void send_umode(struct Client *cptr, struct Client *sptr, int old, int sendmask)
         *m++ = userModeList[i].c;
       }
     }
-    else if (!(flag & old) && (cli_flags(sptr) & flag))
+    else /* !FlagHas(old, flag) */
     {
       if (what == MODE_ADD)
         *m++ = userModeList[i].c;
index 2ba06e4993977d84dd347b159dbe57a833f607e9..4d562b715c9984e24f0e30f0ed10a7109755d00a 100644 (file)
@@ -26,7 +26,7 @@
 #include "class.h"
 #include "client.h"
 #include "ircd.h"
-#include "ircd_policy.h"
+#include "ircd_features.h"
 #include "ircd_snprintf.h"
 #include "ircd_string.h"
 #include "list.h"
@@ -57,7 +57,7 @@ static struct Connection *send_queues = 0;
  *
  * An error has been detected. The link *must* be closed,
  * but *cannot* call ExitClient (m_bye) from here.
- * Instead, mark it with FLAGS_DEADSOCKET. This should
+ * Instead, mark it with FLAG_DEADSOCKET. This should
  * generate ExitClient from the main loop.
  *
  * If 'notice' is not NULL, it is assumed to be a format
@@ -71,7 +71,7 @@ static struct Connection *send_queues = 0;
 
 static void dead_link(struct Client *to, char *notice)
 {
-  cli_flags(to) |= FLAGS_DEADSOCKET;
+  SetFlag(to, FLAG_DEADSOCKET);
   /*
    * If because of BUFFERPOOL problem then clean dbuf's now so that
    * notices don't hurt operators below.
@@ -85,7 +85,7 @@ static void dead_link(struct Client *to, char *notice)
    */
   ircd_strncpy(cli_info(to), notice, REALLEN);
 
-  if (!IsUser(to) && !IsUnknown(to) && !(cli_flags(to) & FLAGS_CLOSING))
+  if (!IsUser(to) && !IsUnknown(to) && !HasFlag(to, FLAG_CLOSING))
     sendto_opmask_butone(0, SNO_OLDSNO, "%s for %s", cli_info(to), cli_name(to));
   Debug((DEBUG_ERROR, cli_info(to)));
 }
@@ -96,6 +96,33 @@ static int can_send(struct Client* to)
   return (IsDead(to) || IsMe(to) || -1 == cli_fd(to)) ? 0 : 1;
 }
 
+/* This helper routine kills the connection with the highest sendq, to
+ * try to free up some buffer memory.
+ */
+void
+kill_highest_sendq(int servers_too)
+{
+  int i;
+  unsigned int highest_sendq = 0;
+  struct Client *highest_client = 0;
+
+  for (i = HighestFd; i >= 0; i--)
+  {
+    if (!LocalClientArray[i] || (!servers_too && cli_serv(LocalClientArray[i])))
+      continue; /* skip servers */
+    
+    /* If this sendq is higher than one we last saw, remember it */
+    if (MsgQLength(&(cli_sendQ(LocalClientArray[i]))) > highest_sendq)
+    {
+      highest_client = LocalClientArray[i];
+      highest_sendq = MsgQLength(&(cli_sendQ(highest_client)));
+    }
+  }
+
+  if (highest_client)
+    dead_link(highest_client, "Buffer allocation error");
+}
+
 /*
  * flush_connections
  *
@@ -456,8 +483,8 @@ void sendcmdto_channel_butone(struct Client *from, const char *cmd,
 
   /* Build buffer to send to users */
   va_start(vd.vd_args, pattern);
-  user_mb = msgq_make(0, skip & SKIP_NONOPS ? "%:#C %s @%v" : "%:#C %s %v",
-                     from, skip & SKIP_NONOPS ? MSG_NOTICE : cmd, &vd);
+  user_mb = msgq_make(0, skip & (SKIP_NONOPS | SKIP_NONVOICES) ? "%:#C %s @%v" : "%:#C %s %v",
+                      from, skip & (SKIP_NONOPS | SKIP_NONVOICES) ? MSG_NOTICE : cmd, &vd);
   va_end(vd.vd_args);
 
   /* Build buffer to send to servers */
@@ -470,11 +497,12 @@ void sendcmdto_channel_butone(struct Client *from, const char *cmd,
   for (member = to->members; member; member = member->next_member) {
     /* skip one, zombies, and deaf users... */
     if (cli_from(member->user) == one || IsZombie(member) ||
-       (skip & SKIP_DEAF && IsDeaf(member->user)) ||
-       (skip & SKIP_NONOPS && !IsChanOp(member)) ||
-       (skip & SKIP_BURST && IsBurstOrBurstAck(cli_from(member->user))) ||
-       cli_fd(cli_from(member->user)) < 0 ||
-       sentalong[cli_fd(cli_from(member->user))] == sentalong_marker)
+        (skip & SKIP_DEAF && IsDeaf(member->user)) ||
+        (skip & SKIP_NONOPS && !IsChanOp(member)) ||
+        (skip & SKIP_NONVOICES && !IsChanOp(member) && !HasVoice(member)) ||
+        (skip & SKIP_BURST && IsBurstOrBurstAck(cli_from(member->user))) ||
+        cli_fd(cli_from(member->user)) < 0 ||
+        sentalong[cli_fd(cli_from(member->user))] == sentalong_marker)
       continue;
     sentalong[cli_fd(cli_from(member->user))] = sentalong_marker;
 
@@ -527,17 +555,15 @@ void sendwallto_group_butone(struct Client *from, int type, struct Client *one,
   va_end(vd.vd_args);
 
   /* send buffer along! */
-  for (i = 0; i <= HighestFd; i++) {
+  for (i = 0; i <= HighestFd; i++)
+  {
     if (!(cptr = LocalClientArray[i]) ||
        (cli_fd(cli_from(cptr)) < 0) ||
-       (type == WALL_DESYNCH && !(cli_flags(cptr) & FLAGS_DEBUG)) ||
-#ifdef HEAD_IN_SAND_WALLOPS
-       (type == WALL_WALLOPS && (!(cli_flags(cptr) & FLAGS_WALLOP) ||
-                                 !IsAnOper(cptr))) ||
-#else
-       (type == WALL_WALLOPS && !(cli_flags(cptr) & FLAGS_WALLOP)) ||
-#endif
-        (type == WALL_WALLUSERS && !(cli_flags(cptr) & FLAGS_WALLOP)))
+       (type == WALL_DESYNCH && !HasFlag(cptr, FLAG_DEBUG)) ||
+       (type == WALL_WALLOPS &&
+         (!HasFlag(cptr, FLAG_WALLOP) || (feature_bool(FEAT_HIS_WALLOPS) &&
+                                          !IsAnOper(cptr)))) ||
+        (type == WALL_WALLUSERS && !HasFlag(cptr, FLAG_WALLOP)))
       continue; /* skip it */
     send_buffer(cptr, mb, 1);
   }
@@ -680,7 +706,8 @@ void vsendto_opmask_butone(struct Client *one, unsigned int mask,
                 &vd);
 
   for (; opslist; opslist = opslist->next)
-    send_buffer(opslist->value.cptr, mb, 0);
+    if (opslist->value.cptr != one)
+      send_buffer(opslist->value.cptr, mb, 0);
 
   msgq_clean(mb);
 }
index 84d6a9c869444b7c99bfc744d46fe0cea25f5aad..ae05bf21ab63421ed2f64c1942f0abe8372674a1 100644 (file)
@@ -34,6 +34,7 @@
 #include "numnicks.h"
 #include "querycmds.h"
 #include "s_misc.h"
+#include "s_stats.h"
 #include "send.h"
 #include "struct.h"
 #include "sys.h"
@@ -200,7 +201,8 @@ void update_load(void)
   last = CurrentTime;
 }
 
-void calc_load(struct Client *sptr)
+void
+calc_load(struct Client *sptr, struct StatDesc *sd, int stat, char *param)
 {
   /* *INDENT-OFF* */
   static const char *header =
index fa8def4b5be396fc45af8c3d7f2529d9c7bc837d..e90ec215fe92eca8d89c7a50a4d94eeae5d38ab7 100644 (file)
@@ -30,7 +30,7 @@
 #include "hash.h"
 #include "ircd.h"
 #include "ircd_chattr.h"
-#include "ircd_policy.h"
+#include "ircd_features.h"
 #include "ircd_reply.h"
 #include "ircd_snprintf.h"
 #include "ircd_string.h"
@@ -138,15 +138,9 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan,
 
   if (!fields || (fields & WHO_FIELD_SER))
   {
-    char *p2;
-#ifdef HEAD_IN_SAND_WHO_SERVERNAME
-    if (IsAnOper(sptr))
-#endif
-      p2 = cli_name(cli_user(acptr)->server);
-#ifdef HEAD_IN_SAND_WHO_SERVERNAME
-    else
-      p2 = HEAD_IN_SAND_SERVERNAME;
-#endif
+    const char *p2 = (feature_bool(FEAT_HIS_WHO_SERVERNAME) && !IsAnOper(sptr)) ?
+                       feature_str(FEAT_HIS_SERVERNAME) :
+                       cli_name(cli_user(acptr)->server);
     *(p1++) = ' ';
     while ((*p2) && (*(p1++) = *(p2++)));
   }
@@ -208,24 +202,31 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan,
     *p1++ = ' ';
     if (!fields)
       *p1++ = ':';              /* Place colon here for default reply */
-#ifdef HEAD_IN_SAND_WHO_HOPCOUNT
-    *p1++ = (sptr == acptr) ? '0' : '3';
-#else
-    /* three digit hopcount maximum */
-    p1 += ircd_snprintf(0, p1, 3, "%d", cli_hopcount(acptr));
-#endif
+    if (feature_bool(FEAT_HIS_WHO_HOPCOUNT) && !IsAnOper(sptr))
+      *p1++ = (sptr == acptr) ? '0' : '3';
+    else
+      /* three digit hopcount maximum */
+      p1 += ircd_snprintf(0, p1, 3, "%d", cli_hopcount(acptr));
   }
 
   if (fields & WHO_FIELD_IDL)
   {
     *p1++ = ' ';
-    if (MyUser(acptr)) {
-           p1 += ircd_snprintf(0, p1, 11, "%d",
-                               CurrentTime - cli_user(acptr)->last);
-    }    
-    else {
-           *p1++ = '0';
-    }
+    if (MyUser(acptr))
+      p1 += ircd_snprintf(0, p1, 11, "%d",
+                          CurrentTime - cli_user(acptr)->last);
+    else
+      *p1++ = '0';
+  }
+
+  if (fields & WHO_FIELD_ACC)
+  {
+    char *p2 = cli_user(acptr)->account;
+    *(p1++) = ' ';
+    if (*p2)
+      while ((*p2) && (*(p1++) = *(p2++)));
+    else
+      *(p1++) = '0';
   }
 
   if (!fields || (fields & WHO_FIELD_REN))