/* - Internet Relay Chat, include/client.h
 *   Copyright (C) 1990 Jarkko Oikarinen and
 *                      University of Oulu, Computing Center
 *
 *   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: client.h,v 1.8 2005/10/05 19:00:09 jpinto Exp $
 */
#ifndef INCLUDED_client_h
#define INCLUDED_client_h
#ifndef INCLUDED_config_h
#include "config.h"
#endif
#if !defined(CONFIG_H_LEVEL_6_1)
#error Incorrect config.h for this revision of ircd.
#endif
#ifndef INCLUDED_sys_types_h
#include <sys/types.h>       /* time_t */
#define INCLUDED_sys_types_h
#endif
#ifndef INCLUDED_netinet_in_h
#include <netinet/in.h>      /* in_addr */
#define INCLUDED_netinet_in_h
#endif
#if defined(HAVE_STDDEF_H)
# ifndef INCLUDED_stddef_h
#  include <stddef.h>        /* offsetof */
#  define INCLUDED_stddef_h
# endif
#endif
#ifndef INCLUDED_ircd_defs_h
# include "ircd_defs.h"
#endif
#ifndef INCLUDED_dbuf_h
#include "dbuf.h"
#endif

#ifdef IPV6
#define HOSTIPLEN       53 /* sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255.ipv6") */
#else
#define HOSTIPLEN       16      /* Length of dotted quad form of IP        */
#endif
#define PASSWDLEN       20
#define IDLEN           12      /* this is the maximum length, not the actual
                                   generated length; DO NOT CHANGE! */
#define CLIENT_BUFSIZE 512      /* must be at least 512 bytes */

/*
 * pre declare structs
 */
struct SLink;
struct ConfItem;
struct Whowas;
struct fludbot;
struct Zdata;
struct Listener;
struct Client;

/*
 * Client structures
 */
struct User
{
  struct User*   next;          /* chain of anUser structures */
  struct SLink*  channel;       /* chain of channel pointer blocks */
  struct SLink*  invited;       /* chain of invite pointer blocks */
  struct SLink*  silence;       /* chain of silence pointer blocks  */
  char*          away;          /* pointer to away message */
  time_t         last;
  int            refcnt;        /* Number of times this block is referenced */
  int            joined;        /* number of channels joined */
  char           id[IDLEN + 1]; /* for future use *hint* */
  const char*    server;        /* pointer to scached server name */
  unsigned int	 news_mask;		/* user subscribed news bit mask */
  struct ConfItem* vlink;       /* virtual link */
  int		lang;		/* user language */
  /*
  ** In a perfect world the 'server' name
  ** should not be needed, a pointer to the
  ** client describing the server is enough.
  ** Unfortunately, in reality, server may
  ** not yet be in links while USER is
  ** introduced... --msa
  */
  /* with auto-removal of dependent links, this may no longer be the
  ** case, but it's already fixed by the scache anyway  -orabidoo
  */
};

struct Server
{
  struct User*     user;        /* who activated this connection */
  const char*      up;          /* Pointer to scache name */
  char             by[NICKLEN + 1];
  struct ConfItem* nline;       /* N-line pointer for this server */
  struct Client*   servers;     /* Servers on this server */
  struct Client*   users;       /* Users on this server */
  char             version[HOSTLEN + 1]; /* server version */
};

struct Client
{
  struct Client*    next;
  struct Client*    prev;
  struct Client*    hnext;
  struct Client*    idhnext;

/* QS */

  struct Client*    lnext;      /* Used for Server->servers/users */
  struct Client*    lprev;      /* Used for Server->servers/users */

/* LINKLIST */
  /* N.B. next_local_client, and previous_local_client
   * duplicate the link list referenced to by struct Server -> users
   * someday, we'll rationalize this... -Dianora
   */

  struct Client*    next_local_client;      /* keep track of these */
  struct Client*    previous_local_client;

  struct Client*    next_server_client;
  struct Client*    next_oper_client;

  struct User*      user;       /* ...defined, if this is a User */
  struct Server*    serv;       /* ...defined, if this is a server */
  struct Client*    servptr;    /* Points to server this Client is on */
  struct Client*    from;       /* == self, if Local Client, *NEVER* NULL! */

  struct Whowas*    whowas;     /* Pointers to whowas structs */
  time_t            lasttime;   /* ...should be only LOCAL clients? --msa */
  time_t            firsttime;  /* time client was created */
  time_t            since;      /* last time we parsed something */
  time_t            tsinfo;     /* TS on the nick, SVINFO on server */
  time_t			nexttarget; /* Time until a change in targets is allowed */
  unsigned char 	targets[MAXTARGETS]; /* Hash values of current targets */
  unsigned int      umodes;     /* opers, normal users subset */
  unsigned int	    imodes;	/* information modes */
  unsigned int      flags;      /* client flags */
  unsigned int      flags2;     /* ugh. overflow */
  int               fd;         /* >= 0, for local clients */
  int               hopcount;   /* number of servers to this 0 = local */
  int    status;     						/* Client type */
  char              nicksent;
  unsigned char     local_flag; /* if this is 1 this client is local */
  short    listprogress;        /* where were we when the /list blocked? */
  int      listprogress2;       /* where in the current bucket were we? */

  /*
   * client->name is the unique name for a client nick or host
   */
  char              name[HOSTLEN + 1]; 
  /* 
   * client->username is the username from ident or the USER message, 
   * If the client is idented the USER message is ignored, otherwise 
   * the username part of the USER message is put here prefixed with a 
   * tilde depending on the I:line, Once a client has registered, this
   * field should be considered read-only.
   */ 
  char              username[USERLEN + 1]; /* client's username */
  /*
   * client->realhost contains the resolved name or ip address
   * as a string for the user, it may be fiddled with for oper spoofing etc.
   * once it's changed the *real* address goes away. This should be
   * considered a read-only field after the client has registered.
   */
  char              realhost[HOSTLEN + 1];     /* client's hostname */
  /*
   * client->host contains a copy of client->realhost if client is coming
   * from a server not using hostname masking or the client hostname masked
   * at the client connection server.
   */
  char              host[HOSTLEN + 1];     /* client's hostname */  
  /*
   * client->info for unix clients will normally contain the info from the 
   * gcos field in /etc/passwd but anything can go here.
   */
  char              info[REALLEN + 1]; /* Free form additional client info */
#ifdef FLUD
  struct SLink*     fludees;
#endif
  /*
   * The following fields are allocated only for local clients
   * (directly connected to *this* server with a socket.
   * The first of them *MUST* be the "count"--it is the field
   * to which the allocation is tied to! *Never* refer to
   * these fields, if (from != self).
   */
  int               count;       /* Amount of data in buffer */
#ifdef FLUD
  time_t            fludblock;
  struct fludbot*   fluders;
#endif
#ifdef ANTI_SPAMBOT
  time_t            last_join_time;   /* when this client last 
                                         joined a channel */
  time_t            last_leave_time;  /* when this client last 
                                       * left a channel */
  int               join_leave_count; /* count of JOIN/LEAVE in less than 
                                         MIN_JOIN_LEAVE_TIME seconds */
  int               oper_warn_count_down; /* warn opers of this possible 
                                          spambot every time this gets to 0 */
#endif
#ifdef ANTI_DRONE_FLOOD
  time_t            first_received_message_time;
  int               received_number_of_privmsgs;
  int               drone_noticed;
#endif
  char  buffer[CLIENT_BUFSIZE]; /* Incoming message buffer */
#ifdef ZIP_LINKS
  struct Zdata*     zip;        /* zip data */
#endif
  short             lastsq;     /* # of 2k blocks when sendqueued called last*/
  struct DBuf       sendQ;      /* Outgoing message queue--if socket full */
  struct DBuf       recvQ;      /* Hold for data incoming yet to be parsed */
  /*
   * we want to use unsigned int here so the sizes have a better chance of
   * staying the same on 64 bit machines. The current trend is to use
   * I32LP64, (32 bit ints, 64 bit longs and pointers) and since ircd
   * will NEVER run on an operating system where ints are less than 32 bits, 
   * it's a relatively safe bet to use ints. Since right shift operations are
   * performed on these, it's not safe to allow them to become negative, 
   * which is possible for long running server connections. Unsigned values 
   * generally overflow gracefully. --Bleep
   */
  unsigned int      sendM;      /* Statistics: protocol messages send */
  unsigned int      sendK;      /* Statistics: total k-bytes send */
  unsigned int      receiveM;   /* Statistics: protocol messages received */
  unsigned int      receiveK;   /* Statistics: total k-bytes received */
  unsigned short    sendB;      /* counters to count upto 1-k lots of bytes */
  unsigned short    receiveB;   /* sent and received. */
  unsigned int      lastrecvM;  /* to check for activity --Mika */
  int               priority;
  struct Listener*  listener;   /* listener accepted from */
  struct SLink*     confs;      /* Configuration record associated */
  struct IN_ADDR    ip;         /* keep real ip# too */
  unsigned short    port;       /* and the remote port# too :-) */
#ifndef USE_ADNS
  struct DNSReply*  dns_reply;  /* result returned from resolver query */  
#else
  struct DNSQuery*  dns_query;  /* result returned from resolver query */  
#endif
#ifdef ANTI_NICK_FLOOD
  time_t            last_nick_change;
  int               number_of_nick_changes;
  int		    services_nick_change;
#endif
  time_t            last_services_use;
  int                number_of_services_use;
  time_t            last_knock; /* don't allow knock to flood */
  /*
   * client->sockhost contains the ip address gotten from the socket as a
   * string, this field should be considered read-only once the connection
   * has been made. (set in s_bsd.c only)
   */
  char              sockhost[HOSTIPLEN + 1]; /* This is the host name from the 
                                              socket ip address as string */
  /*
   * XXX - there is no reason to save this, it should be checked when it's
   * received and not stored, this is not used after registration
   */
  char              passwd[PASSWDLEN + 1];
  struct SLink*     watch; 		/* user's watch list */
  int 				watches; 	/* how many watches this user has set */     
  struct            ListOptions *lopt;          /* Saved /list options */
  int               caps;       /* capabilities bit-field */
  int		    codepage; /* codepage number (index within codepages[]) */
  int               hvc;
  /* SSL support */
#ifdef HAVE_SSL
  int    use_ssl;
  int	 ssl_hshake_done;
  struct SSL*	  ssl;   /* SSL instance */
  struct X509*    client_cert;  /* SSL client's certificate */
#endif  
};

/*
 * status macros.
 */
#define STAT_CONNECTING 0x01 
#define STAT_HANDSHAKE  0x02 
#define STAT_ME         0x04
#define STAT_UNKNOWN    0x08
#define STAT_SERVER     0x10 
#define STAT_CLIENT     0x20 


#define IsRegisteredUser(x)     ((x)->status == STAT_CLIENT)
#define IsRegistered(x)         ((x)->status  > STAT_UNKNOWN)
#define IsConnecting(x)         ((x)->status == STAT_CONNECTING)
#define IsHandshake(x)          ((x)->status == STAT_HANDSHAKE)
#define IsMe(x)                 ((x)->status == STAT_ME)
#define IsUnknown(x)            ((x)->status == STAT_UNKNOWN)
#define IsServer(x)             ((x)->status == STAT_SERVER)
#define IsClient(x)             ((x)->status == STAT_CLIENT)

#define SetConnecting(x)        ((x)->status = STAT_CONNECTING)
#define SetHandshake(x)         ((x)->status = STAT_HANDSHAKE)
#define SetMe(x)                ((x)->status = STAT_ME)
#define SetUnknown(x)           ((x)->status = STAT_UNKNOWN)
#define SetServer(x)            ((x)->status = STAT_SERVER)
#define SetClient(x)            ((x)->status = STAT_CLIENT)

#define STAT_CLIENT_PARSE (STAT_UNKNOWN | STAT_CLIENT)
#define STAT_SERVER_PARSE (STAT_CONNECTING | STAT_HANDSHAKE | STAT_SERVER)

#define PARSE_AS_CLIENT(x)      ((x)->status & STAT_CLIENT_PARSE)
#define PARSE_AS_SERVER(x)      ((x)->status & STAT_SERVER_PARSE)

/*
 * ts stuff
 */
#define TS_CURRENT      10      /* current TS protocol version */
#define TS_MIN          9       /* minimum supported TS protocol version */
#define TS_DOESTS       0x20000000
#define DoesTS(x)       ((x)->tsinfo == TS_DOESTS)


/* housekeeping flags */
#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_BLOCKED      0x0008 /* socket is in a blocked condition */
#define FLAGS_REJECT_HOLD  0x0010 /* client has been klined */
#define FLAGS_CLOSING      0x0020 /* set when closing to suppress errors */
#define FLAGS_CHKACCESS    0x0040 /* ok to check clients access if set */
#define FLAGS_GOTID        0x0080 /* successful ident lookup achieved */
#define FLAGS_NEEDID       0x0100 /* I-lines say must use ident return */
#define FLAGS_NONL         0x0200 /* No \n in buffer */
#define FLAGS_NORMALEX     0x0400 /* Client exited normally */
#define FLAGS_SENDQEX      0x0800 /* Sendq exceeded */
#define FLAGS_IPHASH       0x1000 /* iphashed this client */
#define FLAGS_SERVICE	     0x2000 /* Is Service server/client ? */
#define FLAGS_SSL	   			 0x4000 /* SSL handshake done ? */
#define FLAGS_SCS          0x8000 /* SCS cache synchronized ? */
#define FLAGS_SPATH	   		 0x10000 /* On services path */
#define FLAGS_AUTOAWAY     0x20000 /* user is away from autoaway */
#define FLAGS_WEBHOST			 0x40000 /* user comming from a webchat service? */

/* umodes, settable flags */
#define UMODE_WALLOP       	0x0001 /* send wallops to them */
#define UMODE_INVISIBLE    	0x0002 /* makes user invisible */
#define UMODE_ZOMBIE       	0x0004 /* zombie, settable by command */

/* settable by services */
#define UMODE_IDENTIFIED   	0x0008 /* registered and identified nick */
#define UMODE_SADMIN		0x0010 /* Services admin */

/* user information flags, only settable by remote mode or local oper */
#define UMODE_SSL           	0x00200 /* ssl connection */
#define UMODE_SPY		0x2000 /* for /whois notices */
#define UMODE_OPER         	0x4000 /* Operator */
#define UMODE_LOCOP        	0x8000 /* Local operator -- SRB */


#define UMODE_ADMIN		0x00020000 /* Server Admin */
#define UMODE_TECHADMIN		0x00040000 /* Technical Admin */
#define UMODE_NETADMIN		0x00080000 /* Network Admin */
#define UMODE_HELPER		0x00100000 /* Network Admin */
#define UMODE_BOT		0x00200000 /* bot client */
#define UMODE_NODCC		0x00400000 /* dcc blocked */
#define UMODE_PRIVATE		0x00800000 /* hide channels from whois */
#define UMODE_REGMSG		0x01000000 /* receive privmsg only from +r nicks */
#define UMODE_STEALTH		0x02000000 /* stealth mode */
#define UMODE_HIDEOPER		0x04000000 /* hide oper status */
#define UMODE_FLOODEX		0x08000000 /* flood exempt */

/* end of umodes */


/* information modes (imodes) */
#define IMODE_BOTS		0x00000001 /* bots detection */
#define IMODE_CLIENTS		0x00000002 /* clients connects/quits */
#define IMODE_KILLS		0x00000004 /* kills */
#define IMODE_REJECTS		0x00000008 /* client rejection */
#define IMODE_GENERIC		0x00000010 /* generic */
#define IMODE_VLINES		0x00000020 /* vlines */
#define IMODE_SPY		0x00000040 /* whois/info/motd notices */
#define IMODE_TARGET		0x00000080 /* target limit */
#define IMODE_DEBUG		0x00000100 /* debug */
#define IMODE_EXTERNAL		0x00000200 /* remote connects/squits */
#define IMODE_FULL		0x00000400 /* full server */

/* *sigh* overflow flags */
#define FLAGS2_RESTRICTED   	0x0001      /* restricted client */
#define FLAGS2_PING_TIMEOUT 	0x0002
#define FLAGS2_E_LINED      	0x0004      /* client is graced with E line */
#define FLAGS2_F_LINED      	0x0008      /* client is graced with F line */
#define FLAGS2_EXEMPTGLINE  	0x0010      /* client can't be G-lined */

/* oper priv flags */
#define FLAGS2_OPER_GLOBAL_KILL 0x0020  /* oper can global kill */
#define FLAGS2_OPER_REMOTE      0x0040  /* oper can do squits/connects */
#define FLAGS2_OPER_UNKLINE     0x0080  /* oper can use unkline */
#define FLAGS2_OPER_GLINE       0x0100  /* oper can use gline */
/* #define FLAGS2_OPER_N           0x0200 */ /* oper can umode n */
#define FLAGS2_OPER_K           0x0400  /* oper can kill/kline */
#define FLAGS2_OPER_DIE         0x0800  /* oper can die */
#define FLAGS2_OPER_REHASH      0x1000  /* oper can rehash */
#define FLAGS2_OPER_FLAGS       (FLAGS2_OPER_GLOBAL_KILL | \
                                 FLAGS2_OPER_REMOTE | \
                                 FLAGS2_OPER_UNKLINE | \
                                 FLAGS2_OPER_GLINE | \
                                 FLAGS2_OPER_K | \
                                 FLAGS2_OPER_DIE | \
                                 FLAGS2_OPER_REHASH)
/* ZIP_LINKS */

#define FLAGS2_ZIP           	0x00004000  /* (server) link is zipped */
#define FLAGS2_ZIPFIRST      	0x00008000  /* start of zip (ignore any CR/LF) */
#define FLAGS2_CBURST       	0x000010000  /* connection burst being sent */

#define FLAGS2_DOINGLIST    	0x20000  /* client is doing a list */
#ifdef IDLE_CHECK
#define FLAGS2_IDLE_LINED   	0x40000
#endif
#define FLAGS2_ALREADY_EXITED   0x80000   	/* kludge grrrr */
#define FLAGS2_SENDQ_POP  	0x100000  	/* sendq exceeded (during list) */
#define FLAGS2_WEBCHAT          0x200000  	/* webchat user */

#define USER_UMODES	 (UMODE_INVISIBLE | UMODE_WALLOP | UMODE_HELPER | \
					  UMODE_BOT | UMODE_IDENTIFIED | \
					  UMODE_PRIVATE | UMODE_REGMSG | \
					  UMODE_STEALTH | UMODE_SSL | UMODE_FLOODEX )
#define INTERNAL_UMODES (UMODE_BOT | UMODE_IDENTIFIED | UMODE_STEALTH | \
			UMODE_SADMIN | UMODE_SSL | UMODE_FLOODEX )
#define ALL_UMODES   (USER_UMODES | UMODE_LOCOP | UMODE_SPY | \
			UMODE_OPER | UMODE_LOCOP | UMODE_SADMIN | \
			 UMODE_ZOMBIE | UMODE_HELPER | UMODE_HIDEOPER | \
			 UMODE_ADMIN | UMODE_TECHADMIN | UMODE_NETADMIN )

#ifndef OPER_UMODES
#define OPER_UMODES  (UMODE_OPER | UMODE_WALLOP | UMODE_SPY)
#endif /* OPER_UMODES */

#ifndef LOCOP_UMODES
#define LOCOP_UMODES (UMODE_LOCOP | UMODE_WALLOP | UMODE_SPY)
#endif /* LOCOP_UMODES */

#define FLAGS_ID     (FLAGS_NEEDID | FLAGS_GOTID)

/*
 * flags macros.
 */
#define IsPerson(x)             (IsClient(x) && (x)->user)
#define DoAccess(x)             ((x)->flags & FLAGS_CHKACCESS)
#define IsLocal(x)              ((x)->flags & FLAGS_LOCAL)
#define IsDead(x)               ((x)->flags & FLAGS_DEADSOCKET)
#define SetAccess(x)            ((x)->flags |= FLAGS_CHKACCESS)
#define NoNewLine(x)            ((x)->flags & FLAGS_NONL)
#define ClearAccess(x)          ((x)->flags &= ~FLAGS_CHKACCESS)
#define MyConnect(x)            ((x)->local_flag != 0)
#define MyClient(x)             (MyConnect(x) && IsClient(x))

/* oper flags */
#define MyOper(x)               (MyConnect(x) && IsOper(x))
#define IsOper(x)               ((x)->umodes & UMODE_OPER)
#define IsLocOp(x)              ((x)->umodes & UMODE_LOCOP)
#define IsAnOper(x)             ((x)->umodes & (UMODE_OPER|UMODE_LOCOP))
#define IsHelper(x)		((x)->umodes & UMODE_HELPER)
#define IsSAdmin(x)		((x)->umodes & UMODE_SADMIN)
#define IsAdmin(x)		((x)->umodes & UMODE_ADMIN)
#define IsNetAdmin(x)		((x)->umodes & UMODE_NETADMIN)
#define IsTechAdmin(x)		((x)->umodes & UMODE_TECHADMIN)
#define SetOper(x)              ((x)->umodes |= UMODE_OPER)
#define SetLocOp(x)             ((x)->umodes |= UMODE_LOCOP)
#define SetHelper(x)		((x)->umodes |= UMODE_HELPER)
#define SetSAdmin(x)		((x)->umodes |= UMODE_SADMIN)
#define SetAdmin(x)		((x)->umodes |= UMODE_ADMIN)
#define SetNetAdmin(x)		((x)->umodes |= UMODE_NETADMIN)
#define SetTechAdmin(x)		((x)->umodes |= UMODE_TECHADMIN)
#define ClearOper(x)            ((x)->umodes &= ~UMODE_OPER)
#define ClearLocOp(x)           ((x)->umodes &= ~UMODE_LOCOP)
#define ClearHelper(x)		((x)->umodes &= ~UMODE_HELPER)
#define ClearSAdmin(x)		((x)->umodes &= ~UMODE_SADMIN)
#define ClearAdmin(x)		((x)->umodes &= ~UMODE_ADMIN)
#define ClearNetAdmin(x)	((x)->umodes &= ~UMODE_NETADMIN)
#define ClearTechAdmin(x)	((x)->umodes &= ~UMODE_TECHADMIN)

#define IsPrivileged(x)         (IsAnOper(x) || IsServer(x))

/* umode flags */
#define IsPrivate(x)          	((x)->umodes & UMODE_PRIVATE)

#define IsSsl(x)		((x)->umodes & UMODE_SSL)
#define SetSsl(x)		((x)->umodes |= UMODE_SSL)
#define ClearSsl(x)		((x)->umodes &= ~UMODE_SSL)

#define IsFloodEx(x)		((x)->umodes & UMODE_FLOODEX)
#define SetFloodEx(x)		((x)->umodes |= UMODE_FLOODEX)
#define ClearFloodEx(x)		((x)->umodes &= ~UMODE_FLOODEX)



#define IsStealth(x)		((x)->umodes & UMODE_STEALTH)
#define SetStealth(x)		((x)->umodes |= UMODE_STEALTH)
#define ClearStealth(x)		((x)->umodes &= ~UMODE_STEALTH)

#define IsHideOper(x)		((x)->umodes & UMODE_HIDEOPER)
#define SetHideOper(x)		((x)->umodes |= UMODE_HIDEOPER)
#define ClearHideOper(x)	((x)->umodes &= ~UMODE_HIDEOPER)

#define IsBot(x)          	((x)->umodes & UMODE_BOT)
#define SetBot(x)		((x)->umodes |= UMODE_BOT)
#define ClearBot(x)		((x)->umodes &= ~UMODE_BOT)

#define IsInvisible(x)          ((x)->umodes & UMODE_INVISIBLE)
#define SetInvisible(x)         ((x)->umodes |= UMODE_INVISIBLE)
#define ClearInvisible(x)       ((x)->umodes &= ~UMODE_INVISIBLE)

#define IsIdentified(x)		((x)->umodes & UMODE_IDENTIFIED)
#define SetIdentified(x)        ((x)->umodes |= UMODE_IDENTIFIED)
#define ClearIdentified(x)      ((x)->umodes &= ~UMODE_IDENTIFIED)

#define IsRegMsg(x)		((x)->umodes & UMODE_REGMSG)
#define SetRegMsg(x)        	((x)->umodes |= UMODE_REGMSG)
#define ClearRegMsg(x)      	((x)->umodes &= ~UMODE_REGMSG)

#define IsZombie(x)		((x)->umodes & UMODE_ZOMBIE)
#define SetZombie(x)        	((x)->umodes |= UMODE_ZOMBIE)
#define ClearZombie(x)      	((x)->umodes &= ~UMODE_ZOMBIE)

#define IsNoDCC(x)		((x)->umodes & UMODE_NODCC)
#define SetNoDCC(x)        	((x)->umodes |= UMODE_NODCC)
#define ClearNoDCC(x)      	((x)->umodes &= ~UMODE_NODCC)

#define SendWallops(x)          ((x)->umodes & UMODE_WALLOP)
#define ClearWallops(x)         ((x)->umodes &= ~UMODE_WALLOP)

#define SetWallops(x)           ((x)->umodes |= UMODE_WALLOP)

#define SendSpyNotice(x)        ((x)->umodes & UMODE_SPY)

/* service flags */
#define SetService(x)           ((x)->flags |= FLAGS_SERVICE)
#define IsService(x)        	((x)->flags & FLAGS_SERVICE)
#define ClearService(x)        	((x)->flags &= ~FLAGS_SERVICE)

#define SetServicesPath(x)	((x)->flags |= FLAGS_SPATH)
#define IsServicesPath(x)	((x)->flags & FLAGS_SPATH)
#define ClearServicesPath(x)	 ((x)->flags &= ~FLAGS_SPATH)

/* SCS */
#define SetSCS(x)           ((x)->flags |= FLAGS_SCS)
#define IsSCS(x)        	((x)->flags & FLAGS_SCS)
#define ClearSCS(x)        	((x)->flags &= ~FLAGS_SCS)

/* SSL */
#define SetSecure(x)            ((x)->flags |= FLAGS_SSL)
#define IsSecure(x)        	    ((x)->flags & FLAGS_SSL)


#ifdef REJECT_HOLD
#define IsRejectHeld(x)         ((x)->flags & FLAGS_REJECT_HOLD)
#define SetRejectHold(x)        ((x)->flags |= FLAGS_REJECT_HOLD)
#endif

#define SetIpHash               ((x)->flags |= FLAGS_IPHASH)
#define ClearIpHash             ((x)->flags &= ~FLAGS_IPHASH)
#define IsIpHash                ((x)->flags & FLAGS_IPHASH)

#define SetNeedId(x)            ((x)->flags |= FLAGS_NEEDID)
#define IsNeedId(x)             (((x)->flags & FLAGS_NEEDID) != 0)

#define SetGotId(x)             ((x)->flags |= FLAGS_GOTID)
#define IsGotId(x)              (((x)->flags & FLAGS_GOTID) != 0)

#define SetAutoAway(x)		((x)->flags |= FLAGS_AUTOAWAY)
#define ClearAutoAway(x)	((x)->flags &= ~FLAGS_AUTOAWAY)
#define IsAutoAway(x)		((x)->flags & FLAGS_AUTOAWAY)

#define SetWebHost(x)		((x)->flags |= FLAGS_WEBHOST)
#define ClearWebHost(x)	((x)->flags &= ~FLAGS_WEBHOST)
#define IsWebHost(x)		((x)->flags & FLAGS_WEBHOST)

/*
 * flags2 macros.
 */
#define IsRestricted(x)         ((x)->flags2 & FLAGS2_RESTRICTED)
#define SetRestricted(x)        ((x)->flags2 |= FLAGS2_RESTRICTED)
#define ClearDoingList(x)       ((x)->flags2 &= ~FLAGS2_DOINGLIST)
#define SetDoingList(x)         ((x)->flags2 |= FLAGS2_DOINGLIST)
#define IsDoingList(x)          ((x)->flags2 & FLAGS2_DOINGLIST)
#define ClearSendqPop(x)        ((x)->flags2 &= ~FLAGS2_SENDQ_POP)
#define SetSendqPop(x)          ((x)->flags2 |= FLAGS2_SENDQ_POP)
#define IsSendqPopped(x)        ((x)->flags2 & FLAGS2_SENDQ_POP)
#define SetWebchat(x)           ((x)->flags2 |= FLAGS2_WEBCHAT)
#define IsWebchat(x)            ((x)->flags2 & FLAGS2_WEBCHAT)
#define IsElined(x)             ((x)->flags2 & FLAGS2_E_LINED)
#define SetElined(x)            ((x)->flags2 |= FLAGS2_E_LINED)
#define IsFlined(x)             ((x)->flags2 & FLAGS2_F_LINED)
#define SetFlined(x)            ((x)->flags2 |= FLAGS2_F_LINED)
#define IsExemptGline(x)	  ((x)->flags2 & FLAGS2_EXEMPTGLINE)
#define SetExemptGline(x)	  ((x)->flags2 |= FLAGS2_EXEMPTGLINE)

#ifdef IDLE_CHECK
#define SetIdlelined(x)         ((x)->flags2 |= FLAGS2_IDLE_LINED)
#define IsIdlelined(x)          ((x)->flags2 & FLAGS2_IDLE_LINED)
#endif

#define SetOperGlobalKill(x)    ((x)->flags2 |= FLAGS2_OPER_GLOBAL_KILL)
#define IsOperGlobalKill(x)     ((x)->flags2 & FLAGS2_OPER_GLOBAL_KILL)
#define SetOperRemote(x)        ((x)->flags2 |= FLAGS2_OPER_REMOTE)
#define IsOperRemote(x)         ((x)->flags2 & FLAGS2_OPER_REMOTE)
#define SetOperUnkline(x)       ((x)->flags2 |= FLAGS2_OPER_UNKLINE)
#define IsSetOperUnkline(x)     ((x)->flags2 & FLAGS2_OPER_UNKLINE)
#define SetOperGline(x)         ((x)->flags2 |= FLAGS2_OPER_GLINE)
#define IsSetOperGline(x)       ((x)->flags2 & FLAGS2_OPER_GLINE)
#define SetOperK(x)             ((x)->flags2 |= FLAGS2_OPER_K)
#define IsSetOperK(x)           ((x)->flags2 & FLAGS2_OPER_K)
#define SetOperDie(x)           ((x)->flags2 |= FLAGS2_OPER_DIE)
#define IsOperDie(x)            ((x)->flags2 & FLAGS2_OPER_DIE)
#define SetOperRehash(x)        ((x)->flags2 |= FLAGS2_OPER_REHASH)
#define IsOperRehash(x)         ((x)->flags2 & FLAGS2_OPER_REHASH)
#define CBurst(x)               ((x)->flags2 & FLAGS2_CBURST)

/*
 * 'offsetof' is defined in ANSI-C. The following definition
 * is not absolutely portable (I have been told), but so far
 * it has worked on all machines I have needed it. The type
 * should be size_t but...  --msa
 */
#ifndef offsetof
#define offsetof(t, m) (size_t)((&((t *)0L)->m))
#endif

#define CLIENT_LOCAL_SIZE sizeof(struct Client)
#define CLIENT_REMOTE_SIZE offsetof(struct Client, count)

/*
 * definitions for get_client_name
 */
#define HIDE_IP 0
#define SHOW_IP 1
#define MASK_IP 2
#define REAL_IP 3

extern time_t         check_pings(time_t current);
extern const char*    get_client_name(struct Client* client, int show_ip);
extern const char*    get_client_host(struct Client* client);
extern void           release_client_dns_reply(struct Client* client);
extern void           init_client_heap(void);
extern void           clean_client_heap(void);
extern struct Client* make_client(struct Client* from);
extern void 	      free_client(struct Client* cptr);
extern void           add_client_to_list(struct Client* client);
extern void           remove_client_from_list(struct Client *);
extern void           add_client_to_llist(struct Client** list, 
                                          struct Client* client);
extern void           del_client_from_llist(struct Client** list, 
                                            struct Client* client);
extern int            exit_client(struct Client*, struct Client*, 
                                  struct Client*, const char* comment);

extern void     count_local_client_memory(int *, int *);
extern void     count_remote_client_memory(int *, int *);
extern  int     check_registered (struct Client *);
extern  int     check_registered_user (struct Client *);

extern struct Client* find_chasing (struct Client *, char *, int *);
extern struct Client* find_client(const char* name, struct Client* client);
extern struct Client* find_server_by_name(const char* name);
extern struct Client* find_person (char *, struct Client *);
extern struct Client* find_server(const char* name);
extern struct Client* find_userhost (char *, char *, struct Client *, int *);
extern struct Client* next_client(struct Client* next, const char* name);
extern struct Client* next_client_double(struct Client* next, 
                                         const char* name);

/* 
 * Time we allow clients to spend in unknown state, before tossing.
 */
#define UNKNOWN_TIME 20
#endif /* INCLUDED_client_h */


syntax highlighted by Code2HTML, v. 0.9.1