#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,
struct Client;
struct ConfItem;
+struct StatDesc;
/*
* Structures
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);
* 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.
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 */
(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 */
#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)
#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))
#include <netinet/in.h>
struct Client;
+struct StatDesc;
#define GLINE_MAX_EXPIRE 604800 /* max expire: 7 days */
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 */
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*[]);
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*[]);
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*[]);
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*[]);
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*[]);
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 */
* 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;
*/
struct Client;
+struct StatDesc;
enum Feature {
/* Misc. features */
FEAT_SERVER_PORT,
FEAT_NODEFAULTMOTD,
FEAT_MOTD_BANNER,
+ FEAT_PROVIDER,
FEAT_KILL_IPMISMATCH,
FEAT_IDLE_FROM_MSG,
FEAT_HUB,
FEAT_HOST_HIDING,
FEAT_HIDDEN_HOST,
FEAT_HIDDEN_IP,
+ FEAT_AUTOHIDE,
+ FEAT_CONNEXIT_NOTICES,
/* features that probably should not be touched */
FEAT_KILLCHASETIMELIMIT,
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,
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
};
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);
#endif
struct Client;
+struct StatDesc;
struct Listener {
struct Listener* next; /* list node pointer */
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 */
struct Client;
struct TRecord;
+struct StatDesc;
struct Motd {
struct Motd* next;
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 */
#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
#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"
struct iovec;
struct Client;
+struct StatDesc;
struct MsgCounts {
int alloc;
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 */
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 */
/* 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 */
#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 */
*/
extern char *militime(char* sec, char* usec);
+extern char *militime_float(char *start);
#endif /* INCLUDED_opercmds_h */
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 {
struct ConnectionClass* conn_class;
};
+struct qline
+{
+ struct qline *next;
+ char *chname;
+ char *reason;
+};
+
struct DenyConf {
struct DenyConf* next;
char* hostmask;
extern struct MotdItem* motd;
extern struct MotdItem* rmotd;
extern struct TRecord* tdata;
+extern struct qline* GlobalQuarantineList;
/*
* Proto types
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);
#endif
struct Client;
+struct StatDesc;
#ifdef DEBUGMODE
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 */
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 */
struct Client;
+struct StatDesc;
struct ConfItem;
/*-----------------------------------------------------------------------------
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;
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 */
struct User;
struct Channel;
struct MsgBuf;
+struct Flags;
/*
* Macros
#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
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,
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 *);
*/
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);
#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,
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];
#define FEATURES1 \
"WHOX"\
" WALLCHOPS"\
+ " WALLVOICES"\
" USERIP"\
" CPRIVMSG"\
" CNOTICE"\
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 */
#define INCLUDED_userload_h
struct Client;
+struct StatDesc;
/*
* Structures
*/
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;
#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)) )
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;
}
listener.c \
m_account.c \
m_admin.c \
+ m_asll.c \
m_away.c \
m_burst.c \
m_clearmode.c \
m_wallchops.c \
m_wallops.c \
m_wallusers.c \
+ m_wallvoices.c \
m_who.c \
m_whois.c \
m_whowas.c \
#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"
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);
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];
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)) {
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
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)
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;
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,
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);
return;
state->done |= DONE_KEY;
- t_len = KEYLEN + 1;
+ t_len = KEYLEN;
/* clean up the key string */
s = t_str;
} 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 */
}
}
} 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--;
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,
joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, unsigned int flags)
{
unsigned int len;
+ int is_local;
assert(0 != jbuf);
return;
}
+ is_local = IsLocalChannel(chan->chname);
+
if (jbuf->jb_type == JOINBUF_TYPE_PART ||
jbuf->jb_type == JOINBUF_TYPE_PARTALL) {
/* Send notification to channel */
* 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);
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 */
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;
+}
}
void
-report_classes(struct Client *sptr)
+report_classes(struct Client *sptr, struct StatDesc *sd, int stat,
+ char *param)
{
struct ConnectionClass *cltmp;
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.
/* 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))
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 }
};
#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"
#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"
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))
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 */
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 */
/* 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,
/* 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,
}
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;
}
void
-gline_stats(struct Client *sptr)
+gline_stats(struct Client *sptr, struct StatDesc *sd, int stat,
+ char *param)
{
struct Gline *gline;
struct Gline *sgline;
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;
+}
+
#include "msg.h"
#include "numeric.h"
#include "numnicks.h"
+#include "opercmds.h"
#include "parse.h"
#include "res.h"
#include "s_auth.h"
/*----------------------------------------------------------------------------
* 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);
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 */
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))));
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;
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),
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),
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),
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
/* report all F-lines */
void
-feature_report(struct Client* to)
+feature_report(struct Client* to, struct StatDesc* sd, int stat, char* param)
{
int i;
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;
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 */
{
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",
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 :/... */
struct ConfItem *aconf;
struct DenyConf *dconf;
struct ServerConf *sconf;
+ struct qline *qconf = NULL;
%}
%token <text> QSTRING
%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. */
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)
* 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;
};
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; } |
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);
+};
#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"
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;
* 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))
{
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++;
#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"
/* 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);
/* 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);
/* 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);
/* 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;
+}
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
*/
#include "s_bsd.h"
#include "s_conf.h"
#include "s_misc.h"
+#include "s_stats.h"
#include "send.h"
#include "sys.h" /* MAXCLIENTS */
* 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;
* 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
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);
}
}
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);
#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"
*/
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);
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);
}
--- /dev/null
+/*
+ * 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;
+}
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 {
#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"
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;
* 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);
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 */
#include "msg.h"
#include "numeric.h"
#include "numnicks.h"
+#include "s_conf.h"
#include "send.h"
#include "support.h"
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)
{
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");
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);
}
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.
*/
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, ",")) {
if (IsLocalChannel(name))
continue;
- if ((chptr = FindChannel(name))) {
+ if ((chptr = FindChannel(name)))
+ {
name = chptr->chname;
/* Check if we need to bounce a mode */
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 */
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')) {
} 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");
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))
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);
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;
}
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;
#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.
struct ModeBuf mbuf;
struct Gline *gline;
unsigned int flags = 0;
- int i;
+ int i, j, k = 0;
char *p = 0;
char *chanlist;
char *name;
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;
}
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)) {
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))) */
}
} 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);
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')
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;
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)
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");
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)))
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");
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);
#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, char* msg)
{
assert(0 != cptr);
assert(0 != sptr);
- assert(IsUser(victim));
+ assert(!IsServer(victim));
/*
* Notify all *local* opers about the KILL (this includes the one
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);
}
/*
* 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
}
/*
#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)
{
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;
+ }
{
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,
#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;
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;
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);
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))
#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;
* 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);
#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
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);
* "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;
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
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)
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);
char* name;
char* server;
- cli_flags(sptr) &= ~FLAGS_TS8;
+ ClrFlag(sptr, FLAG_TS8);
if (parc < 3) {
/*
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);
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));
}
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);
}
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)",
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));
/*
* 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;
{
struct Channel *chptr = 0;
struct ModeBuf mbuf;
+ char *chname, *qreason;
+ int force = 0;
struct Membership *member;
if (!feature_bool(FEAT_CONFIG_OPERCMDS))
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);
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')
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')
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);
}
#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>
/*
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);
#include "msg.h"
#include "numeric.h"
#include "numnicks.h"
+#include "opercmds.h"
#include "s_user.h"
#include "send.h"
}
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;
}
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
{
assert(0 != cptr);
assert(cptr == sptr);
- cli_flags(cptr) &= ~FLAGS_PINGSENT;
+ ClrFlag(cptr, FLAG_PINGSENT);
cli_lasttime(cptr) = CurrentTime;
return 0;
}
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;
char* name;
char* server;
- cli_flags(sptr) &= ~FLAGS_TS8;
+ ClrFlag(sptr, FLAG_TS8);
if (parc < 3) {
/*
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;
#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>
*
* 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");
}
}
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");
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)
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;
{
const char* server = parv[1];
struct Client *acptr;
- time_t timestamp;
+ time_t timestamp = 0;
char *comment = 0;
if (parc < 2)
}
/* 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;
}
*/
#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;
-}
-
#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));
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);
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))
#include "client.h"
#include "hash.h"
#include "ircd.h"
+#include "ircd_features.h"
#include "ircd_reply.h"
#include "ircd_string.h"
#include "match.h"
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
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>" */
#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;
}
* 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[])
{
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());
* 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[])
{
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");
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]);
--- /dev/null
+/*
+ * 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;
+}
#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"
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))
{
&& ((!(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))
&& ((!(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))
#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"
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));
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));
}
* 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)
#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"
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++;
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 = '`';
#include "s_conf.h"
#include "s_debug.h"
#include "s_user.h"
+#include "s_stats.h"
#include "send.h"
#include <assert.h>
{
struct Motd* tmp;
int type = MOTD_UNIVERSAL;
+ const char *s;
assert(0 != path);
/* 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;
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)));
+}
#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
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 */
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
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;
}
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));
}
/*
{
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;
}
}
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 {
* 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;
}
/*
{
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]);
}
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++;
}
}
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/time.h>
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;
+}
#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"
/* 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,
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,
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,
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,
/* 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
unsigned char *d = (unsigned char *)dest;
unsigned char *s = (unsigned char *)src;
- while (--n)
+ while (n--)
d[n] ^= s[n];
}
{ "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 {
REPORT_DO_ID,
REPORT_FIN_ID,
REPORT_FAIL_ID,
- REPORT_IP_MISMATCH
+ REPORT_IP_MISMATCH,
+ REPORT_INVAL_DNS
} ReportType;
#define sendheader(c, r) \
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
*/
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);
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;
* 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;
* 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,
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));
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;
}
}
* 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)));
}
*/
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)));
}
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);
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));
#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 ConfItem* GlobalConfList = 0;
+struct ConfItem *GlobalConfList = 0;
int GlobalConfCount = 0;
+struct qline *GlobalQuarantineList = 0;
void yyparse(void);
int conf_fd, lineno;
* 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;
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);
}
}
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);
}
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
*
* 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);
}
#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;
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 */
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 */
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;
awm += (strlen(cli_user(acptr)->away) + 1);
}
}
+
+ if (IsAccount(acptr))
+ acc++;
}
cm = c * sizeof(struct Client);
cnm = cn * sizeof(struct Connection);
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,
":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);
/* 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 */
/* 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 */
/* 523 */
{ 0 },
/* 524 */
- { 0 },
+ { ERR_QUARANTINED, "%s :Channel is quarantined : %s", "524" },
/* 525 */
{ 0 },
/* 526 */
#include "ircd_snprintf.h"
#include "ircd_string.h"
#include "list.h"
+#include "map.h"
#include "match.h"
#include "msg.h"
#include "numeric.h"
#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"
#include "sys.h"
#include "uping.h"
#include "userload.h"
-#include "map.h"
#include <assert.h>
#include <fcntl.h>
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;
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);
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 ||
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);
}
/*
* 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);
}
}
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;
#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"
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;
}
*/
#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'},
{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)
{
}
}
-/*
- * {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)
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;
+ }
+ }
+}
#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"
return HUNTED_NOSUCH;
}
- assert(!IsServer(from));
+ /* assert(!IsServer(from)); */
parv[server] = (char *) acptr; /* HACK! HACK! HACK! ARGH! */
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
short badid = 0;
short digitgroups = 0;
struct User* user = cli_user(sptr);
+ struct Flags flag;
char ip_base64[8];
user->last = CurrentTime;
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')))
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++;
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...
*/
/* 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
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
* 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
*/
/* 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));
}
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)
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;
}
* 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);
*
* 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
*/
assert(cli_local(sptr));
targets = cli_targets(sptr);
+
+ if (IsChannelName(cli_name(sptr)) && IsInvited(sptr, target))
+ return;
/*
* Already in table?
*/
/*
* 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);
* 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.
*
struct Client *acptr;
int what;
int i;
- int setflags;
+ struct Flags setflags;
unsigned int tmpmask = 0;
int snomask_given = 0;
char buf[BUFSIZE];
{
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));
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;
}
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;
}
* 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;
}
*/
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++ = ' ';
* 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;
/*
* 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;
*m++ = userModeList[i].c;
}
}
- else if (!(flag & old) && (cli_flags(sptr) & flag))
+ else /* !FlagHas(old, flag) */
{
if (what == MODE_ADD)
*m++ = userModeList[i].c;
#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"
*
* 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
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.
*/
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)));
}
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
*
/* 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 */
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;
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);
}
&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);
}
#include "numnicks.h"
#include "querycmds.h"
#include "s_misc.h"
+#include "s_stats.h"
#include "send.h"
#include "struct.h"
#include "sys.h"
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 =
#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"
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++)));
}
*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))