mirror of
git://git.acid.vegas/unrealircd.git
synced 2024-11-27 10:26:54 +00:00
2479 lines
94 KiB
C
2479 lines
94 KiB
C
/************************************************************************
|
|
* Unreal Internet Relay Chat Daemon, include/struct.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$
|
|
*/
|
|
|
|
#ifndef __struct_include__
|
|
#define __struct_include__
|
|
|
|
#include "config.h"
|
|
#include "sys.h"
|
|
/* need to include ssl stuff here coz otherwise you get
|
|
* conflicting types with isalnum/isalpha/etc @ redhat. -- Syzop
|
|
*/
|
|
#define OPENSSL_NO_KRB5
|
|
#include <openssl/rsa.h> /* SSL stuff */
|
|
#include <openssl/crypto.h>
|
|
#include <openssl/x509.h>
|
|
#include <openssl/pem.h>
|
|
#include <openssl/ssl.h>
|
|
#include <openssl/err.h>
|
|
#include <openssl/evp.h>
|
|
#include <openssl/rand.h>
|
|
#include <openssl/md5.h>
|
|
#include <openssl/ripemd.h>
|
|
#ifdef HAS_X509_check_host
|
|
#include <openssl/x509v3.h>
|
|
#endif
|
|
#include <jansson.h>
|
|
#include "common.h"
|
|
#include "sys.h"
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#ifndef _WIN32
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
#include <stddef.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_SYSLOG
|
|
# include <syslog.h>
|
|
# ifdef SYSSYSLOGH
|
|
# include <sys/syslog.h>
|
|
# endif
|
|
#ifndef UNREAL_LOGGER_CODE
|
|
/* undef these as they cause confusion with our ULOG_xxx codes */
|
|
#undef LOG_DEBUG
|
|
#undef LOG_INFO
|
|
#undef LOG_WARNING
|
|
#undef LOG_ERROR
|
|
#undef LOG_FATAL
|
|
#endif
|
|
#endif
|
|
#define PCRE2_CODE_UNIT_WIDTH 8
|
|
#include "pcre2.h"
|
|
|
|
#include "channel.h"
|
|
|
|
typedef struct LoopStruct LoopStruct;
|
|
typedef struct TKL TKL;
|
|
typedef struct Spamfilter Spamfilter;
|
|
typedef struct ServerBan ServerBan;
|
|
typedef struct BanException BanException;
|
|
typedef struct NameBan NameBan;
|
|
typedef struct SpamExcept SpamExcept;
|
|
typedef struct ConditionalConfig ConditionalConfig;
|
|
typedef struct ConfigEntry ConfigEntry;
|
|
typedef struct ConfigFile ConfigFile;
|
|
typedef struct ConfigFlag ConfigFlag;
|
|
typedef struct ConfigFlag_except ConfigFlag_except;
|
|
typedef struct ConfigFlag_ban ConfigFlag_ban;
|
|
typedef struct ConfigFlag_tld ConfigFlag_tld;
|
|
typedef struct ConfigItem ConfigItem;
|
|
typedef struct ConfigItem_me ConfigItem_me;
|
|
typedef struct ConfigItem_files ConfigItem_files;
|
|
typedef struct ConfigItem_admin ConfigItem_admin;
|
|
typedef struct ConfigItem_class ConfigItem_class;
|
|
typedef struct ConfigItem_oper ConfigItem_oper;
|
|
typedef struct ConfigItem_operclass ConfigItem_operclass;
|
|
typedef struct ConfigItem_mask ConfigItem_mask;
|
|
typedef struct ConfigItem_drpass ConfigItem_drpass;
|
|
typedef struct ConfigItem_ulines ConfigItem_ulines;
|
|
typedef struct ConfigItem_tld ConfigItem_tld;
|
|
typedef struct ConfigItem_listen ConfigItem_listen;
|
|
typedef struct ConfigItem_sni ConfigItem_sni;
|
|
typedef struct ConfigItem_allow ConfigItem_allow;
|
|
typedef struct ConfigFlag_allow ConfigFlag_allow;
|
|
typedef struct ConfigItem_allow_channel ConfigItem_allow_channel;
|
|
typedef struct ConfigItem_allow_dcc ConfigItem_allow_dcc;
|
|
typedef struct ConfigItem_vhost ConfigItem_vhost;
|
|
typedef struct ConfigItem_link ConfigItem_link;
|
|
typedef struct ConfigItem_ban ConfigItem_ban;
|
|
typedef struct ConfigItem_deny_dcc ConfigItem_deny_dcc;
|
|
typedef struct ConfigItem_deny_channel ConfigItem_deny_channel;
|
|
typedef struct ConfigItem_deny_version ConfigItem_deny_version;
|
|
typedef struct ConfigItem_alias ConfigItem_alias;
|
|
typedef struct ConfigItem_alias_format ConfigItem_alias_format;
|
|
typedef struct ConfigResource ConfigResource;
|
|
typedef struct ConfigItem_blacklist_module ConfigItem_blacklist_module;
|
|
typedef struct ConfigItem_help ConfigItem_help;
|
|
typedef struct ConfigItem_offchans ConfigItem_offchans;
|
|
typedef struct SecurityGroup SecurityGroup;
|
|
typedef struct Secret Secret;
|
|
typedef struct ListStruct ListStruct;
|
|
typedef struct ListStructPrio ListStructPrio;
|
|
|
|
#define CFG_TIME 0x0001
|
|
#define CFG_SIZE 0x0002
|
|
#define CFG_YESNO 0x0004
|
|
|
|
typedef struct Watch Watch;
|
|
typedef struct Client Client;
|
|
typedef struct LocalClient LocalClient;
|
|
typedef struct Channel Channel;
|
|
typedef struct User User;
|
|
typedef struct Server Server;
|
|
typedef struct RPCClient RPCClient;
|
|
typedef struct Link Link;
|
|
typedef struct Ban Ban;
|
|
typedef struct Mode Mode;
|
|
typedef struct MessageTag MessageTag;
|
|
typedef struct MOTDFile MOTDFile; /* represents a whole MOTD, including remote MOTD support info */
|
|
typedef struct MOTDLine MOTDLine; /* one line of a MOTD stored as a linked list */
|
|
|
|
typedef struct RealCommand RealCommand;
|
|
typedef struct CommandOverride CommandOverride;
|
|
typedef struct Member Member;
|
|
typedef struct Membership Membership;
|
|
|
|
typedef enum OperClassEntryType { OPERCLASSENTRY_ALLOW=1, OPERCLASSENTRY_DENY=2} OperClassEntryType;
|
|
|
|
typedef enum OperPermission { OPER_ALLOW=1, OPER_DENY=0} OperPermission;
|
|
|
|
typedef enum SendType {
|
|
SEND_TYPE_PRIVMSG = 0,
|
|
SEND_TYPE_NOTICE = 1,
|
|
SEND_TYPE_TAGMSG = 2
|
|
} SendType;
|
|
|
|
struct OperClassValidator;
|
|
typedef struct OperClassValidator OperClassValidator;
|
|
typedef struct OperClassACLPath OperClassACLPath;
|
|
typedef struct OperClass OperClass;
|
|
typedef struct OperClassACL OperClassACL;
|
|
typedef struct OperClassACLEntry OperClassACLEntry;
|
|
typedef struct OperClassACLEntryVar OperClassACLEntryVar;
|
|
typedef struct OperClassCheckParams OperClassCheckParams;
|
|
|
|
typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* variables,OperClassCheckParams* params);
|
|
|
|
#ifndef VMSP
|
|
#include "dbuf.h" /* THIS REALLY SHOULDN'T BE HERE!!! --msa */
|
|
#endif
|
|
|
|
#define HOSTLEN 63 /* Length of hostname */
|
|
#define NICKLEN 30
|
|
#define USERLEN 10
|
|
#define REALLEN 50
|
|
#define ACCOUNTLEN 30
|
|
#define MAXTOPICLEN 360 /* absolute maximum permitted topic length (above this = potential desync) */
|
|
#define MAXAWAYLEN 360 /* absolute maximum permitted away length (above this = potential desync) */
|
|
#define MAXKICKLEN 360 /* absolute maximum kick length (above this = only cutoff danger) */
|
|
#define MAXQUITLEN 395 /* absolute maximum quit length (above this = only cutoff danger) */
|
|
#define CHANNELLEN 32
|
|
#define PASSWDLEN 256 /* some insane large limit (previously: 20, 32, 48) */
|
|
#define KEYLEN 23
|
|
#define LINKLEN 32
|
|
#define BUFSIZE 512 /* WARNING: *DONT* CHANGE THIS!!!! */
|
|
#define MAXTAGSIZE 8192 /**< Maximum length of message tags (4K user + 4K server) */
|
|
#define MAXLINELENGTH (MAXTAGSIZE+BUFSIZE) /**< Maximum length of a line on IRC: 4k client tags + 4k server tags + 512 bytes (IRCv3) */
|
|
#define READBUFSIZE MAXLINELENGTH /* for the read buffer */
|
|
#define MAXRECIPIENTS 20
|
|
#define MAXSILELENGTH NICKLEN+USERLEN+HOSTLEN+10
|
|
#define IDLEN 12
|
|
#define SIDLEN 3
|
|
#define SWHOISLEN 256
|
|
#define UMODETABLESZ (sizeof(long) * 8)
|
|
#define MAXCCUSERS 20 /* Maximum for set::anti-flood::max-concurrent-conversations */
|
|
#define BATCHLEN 22
|
|
|
|
/*
|
|
* Watch it - Don't change this unless you also change the ERR_TOOMANYWATCH
|
|
* and PROTOCOL_SUPPORTED settings.
|
|
*/
|
|
#define MAXWATCH 128
|
|
|
|
#define USERHOST_REPLYLEN (NICKLEN+HOSTLEN+USERLEN+5)
|
|
|
|
/* NOTE: this must be down here so the stuff from struct.h IT uses works */
|
|
#include "whowas.h"
|
|
|
|
/* Logging types */
|
|
#define LOG_ERROR 0x0001
|
|
#define LOG_KILL 0x0002
|
|
#define LOG_SACMDS 0x0080
|
|
#define LOG_CHGCMDS 0x0100
|
|
#define LOG_OVERRIDE 0x0200
|
|
|
|
typedef enum LogFieldType {
|
|
LOG_FIELD_INTEGER, // and unsigned?
|
|
LOG_FIELD_STRING,
|
|
LOG_FIELD_CLIENT,
|
|
LOG_FIELD_CHANNEL,
|
|
LOG_FIELD_OBJECT
|
|
} LogFieldType;
|
|
|
|
typedef struct LogData {
|
|
LogFieldType type;
|
|
char *key;
|
|
union {
|
|
int64_t integer;
|
|
char *string;
|
|
Client *client;
|
|
Channel *channel;
|
|
json_t *object;
|
|
} value;
|
|
} LogData;
|
|
|
|
/** New log levels for unreal_log() */
|
|
/* Note: the reason for these high numbers is so we can easily catch
|
|
* if someone makes a mistake to use LOG_INFO (from syslog.h) instead
|
|
* of the ULOG_xxx levels.
|
|
*/
|
|
typedef enum LogLevel {
|
|
ULOG_INVALID = 0,
|
|
ULOG_DEBUG = 1000,
|
|
ULOG_INFO = 2000,
|
|
ULOG_WARNING = 3000,
|
|
ULOG_ERROR = 4000,
|
|
ULOG_FATAL = 5000
|
|
} LogLevel;
|
|
|
|
/** Logging types (text, json, etc) */
|
|
typedef enum LogType {
|
|
LOG_TYPE_INVALID = 0,
|
|
LOG_TYPE_TEXT = 1,
|
|
LOG_TYPE_JSON = 2,
|
|
} LogType;
|
|
|
|
#define LOG_CATEGORY_LEN 32
|
|
#define LOG_EVENT_ID_LEN 64
|
|
typedef struct LogSource LogSource;
|
|
struct LogSource {
|
|
LogSource *prev, *next;
|
|
LogLevel loglevel;
|
|
char negative; /**< 1 if negative match (eg !operoverride), 0 if normal */
|
|
char subsystem[LOG_CATEGORY_LEN+1];
|
|
char event_id[LOG_EVENT_ID_LEN+1];
|
|
};
|
|
|
|
typedef struct Log Log;
|
|
struct Log {
|
|
Log *prev, *next;
|
|
LogSource *sources;
|
|
int type;
|
|
char destination[CHANNELLEN+1];
|
|
int show_event;
|
|
/* for destination::file */
|
|
char *file;
|
|
char *filefmt;
|
|
long maxsize;
|
|
int logfd;
|
|
/* for destination::channel */
|
|
int color;
|
|
int json_message_tag;
|
|
int oper_only;
|
|
};
|
|
|
|
/** This is used for deciding the <index> in logs[<index>] and temp_logs[<index>] */
|
|
typedef enum LogDestination { LOG_DEST_SNOMASK=0, LOG_DEST_OPER=1, LOG_DEST_REMOTE=2, LOG_DEST_CHANNEL=3, LOG_DEST_DISK=4 } LogDestination;
|
|
#define NUM_LOG_DESTINATIONS 5
|
|
|
|
/*
|
|
** '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) (int)((&((t *)0L)->m))
|
|
#endif
|
|
|
|
#define elementsof(x) (sizeof(x)/sizeof(x[0]))
|
|
|
|
/* Calculate the size of an array */
|
|
#define ARRAY_SIZEOF(x) (sizeof((x))/sizeof((x)[0]))
|
|
|
|
/*
|
|
** flags for bootup options (command line flags)
|
|
*/
|
|
#define BOOT_DEBUG 1
|
|
#define BOOT_TTY 2
|
|
#define BOOT_NOFORK 4
|
|
|
|
/* Length of the key that you feed into siphash_generate_key()
|
|
* DO NOT CHANGE THIS as the siphash code depends on it.
|
|
*/
|
|
#define SIPHASH_KEY_LENGTH 16
|
|
|
|
/** The length of a standard 'msgid' tag (note that special
|
|
* msgid tags will be longer).
|
|
* The 22 alphanumeric characters provide slightly more
|
|
* than 128 bits of randomness (62^22 > 2^128).
|
|
* See mtag_add_or_inherit_msgid() for more information.
|
|
*/
|
|
#define MSGIDLEN 22
|
|
|
|
/** This specifies the current client status or the client type - see @link ClientStatus @endlink in particular.
|
|
* You may think "server" or "client" are the only choices here, but there are many more
|
|
* such as states where the user is in the middle of an TLS handshake.
|
|
* @defgroup ClientStatuses Client statuses / types
|
|
* @{
|
|
*/
|
|
typedef enum ClientStatus {
|
|
CLIENT_STATUS_RPC = -10, /**< RPC Client (either local or remote) */
|
|
CLIENT_STATUS_CONTROL = -9, /**< Client is on the control channel */
|
|
CLIENT_STATUS_LOG = -8, /**< Client is a log file */
|
|
CLIENT_STATUS_TLS_STARTTLS_HANDSHAKE = -7, /**< Client is doing a STARTTLS handshake */
|
|
CLIENT_STATUS_CONNECTING = -6, /**< Client is an outgoing connect */
|
|
CLIENT_STATUS_TLS_CONNECT_HANDSHAKE = -5, /**< Client is doing an TLS handshake - outgoing connection */
|
|
CLIENT_STATUS_TLS_ACCEPT_HANDSHAKE = -4, /**< Client is doing an TLS handshake - incoming connection */
|
|
CLIENT_STATUS_HANDSHAKE = -3, /**< Client is doing a server handshake - outgoing connection */
|
|
CLIENT_STATUS_ME = -2, /**< Client is &me (this server) */
|
|
CLIENT_STATUS_UNKNOWN = -1, /**< Client is doing a hanshake. May become a server or user later, we don't know yet */
|
|
CLIENT_STATUS_SERVER = 0, /**< Client is a server (fully authenticated) */
|
|
CLIENT_STATUS_USER = 1, /**< Client is a user (fully authenticated) */
|
|
} ClientStatus;
|
|
|
|
#define MyConnect(x) ((x)->local) /**< Is a locally connected client (server or user) */
|
|
#define MyUser(x) (MyConnect(x) && IsUser(x)) /**< Is a locally connected user */
|
|
#define IsUser(x) ((x)->status == CLIENT_STATUS_USER) /**< Is a user that has completed the connection handshake */
|
|
#define IsRegistered(x) ((x)->status >= CLIENT_STATUS_SERVER) /**< Client has completed the connection handshake (user or server) */
|
|
#define IsConnecting(x) ((x)->status == CLIENT_STATUS_CONNECTING) /**< Is an outgoing connect to another server */
|
|
#define IsHandshake(x) ((x)->status == CLIENT_STATUS_HANDSHAKE) /**< Is doing a handshake (while connecting to another server) */
|
|
#define IsMe(x) ((x)->status == CLIENT_STATUS_ME) /**< This is true for &me */
|
|
/** Client is not fully registered yet. May become a user or a server, we don't know yet. */
|
|
#define IsUnknown(x) (((x)->status == CLIENT_STATUS_UNKNOWN) || ((x)->status == CLIENT_STATUS_TLS_STARTTLS_HANDSHAKE))
|
|
#define IsServer(x) ((x)->status == CLIENT_STATUS_SERVER) /**< Is a server that has completed the connection handshake */
|
|
#define IsControl(x) ((x)->status == CLIENT_STATUS_CONTROL) /**< Is on the control channel (not an IRC client) */
|
|
#define IsRPC(x) ((x)->status == CLIENT_STATUS_RPC) /**< Is doing RPC (not an IRC client) */
|
|
#define IsLog(x) ((x)->status == CLIENT_STATUS_LOG) /**< Is a log file, not a user or server */
|
|
#define IsStartTLSHandshake(x) ((x)->status == CLIENT_STATUS_TLS_STARTTLS_HANDSHAKE) /**< Currently doing a STARTTLS handshake */
|
|
#define IsTLSAcceptHandshake(x) ((x)->status == CLIENT_STATUS_TLS_ACCEPT_HANDSHAKE) /**< Currently doing a TLS handshake - incoming */
|
|
#define IsTLSConnectHandshake(x) ((x)->status == CLIENT_STATUS_TLS_CONNECT_HANDSHAKE) /**< Currently doing a TLS handshake - outgoing */
|
|
#define IsTLSHandshake(x) (IsTLSAcceptHandshake(x) || IsTLSConnectHandshake(x) | IsStartTLSHandshake(x)) /**< Currently doing a TLS handshake (incoming/outgoing/STARTTLS) */
|
|
|
|
#define SetStartTLSHandshake(x) ((x)->status = CLIENT_STATUS_TLS_STARTTLS_HANDSHAKE)
|
|
#define SetTLSAcceptHandshake(x) ((x)->status = CLIENT_STATUS_TLS_ACCEPT_HANDSHAKE)
|
|
#define SetTLSConnectHandshake(x) ((x)->status = CLIENT_STATUS_TLS_CONNECT_HANDSHAKE)
|
|
#define SetConnecting(x) ((x)->status = CLIENT_STATUS_CONNECTING)
|
|
#define SetHandshake(x) ((x)->status = CLIENT_STATUS_HANDSHAKE)
|
|
#define SetMe(x) ((x)->status = CLIENT_STATUS_ME)
|
|
#define SetUnknown(x) ((x)->status = CLIENT_STATUS_UNKNOWN)
|
|
#define SetServer(x) ((x)->status = CLIENT_STATUS_SERVER)
|
|
#define SetUser(x) ((x)->status = CLIENT_STATUS_USER)
|
|
#define SetLog(x) ((x)->status = CLIENT_STATUS_LOG)
|
|
#define SetControl(x) ((x)->status = CLIENT_STATUS_CONTROL)
|
|
#define SetRPC(x) ((x)->status = CLIENT_STATUS_RPC)
|
|
#define SetUser(x) ((x)->status = CLIENT_STATUS_USER)
|
|
|
|
/** @} */
|
|
|
|
/** Used for checking certain properties of clients, such as IsSecure() and IsULine().
|
|
* @defgroup ClientFlags Client flags
|
|
* @{
|
|
*/
|
|
#define CLIENT_FLAG_PINGSENT 0x00000001 /**< PING sent, no reply yet */
|
|
#define CLIENT_FLAG_DEAD 0x00000002 /**< Client is dead: already quit/exited and removed from all lists -- Remaining part will soon be freed in main loop */
|
|
#define CLIENT_FLAG_DEADSOCKET 0x00000004 /**< Local socket is dead but otherwise the client still exists fully -- Will soon exit in main loop */
|
|
#define CLIENT_FLAG_KILLED 0x00000008 /**< Prevents "QUIT" from being sent for this */
|
|
#define CLIENT_FLAG_MONITOR_REHASH 0x00000010 /**< Client is monitoring rehash output */
|
|
#define CLIENT_FLAG_OUTGOING 0x00000020 /**< Outgoing connection (do not touch cptr->listener->clients) */
|
|
#define CLIENT_FLAG_CLOSING 0x00000040 /**< Set when closing to suppress errors */
|
|
#define CLIENT_FLAG_LISTEN 0x00000080 /**< Used to mark clients which we listen() on */
|
|
#define CLIENT_FLAG_DNSLOOKUP 0x00000100 /**< Client is doing a DNS lookup */
|
|
#define CLIENT_FLAG_IDENTLOOKUP 0x00000200 /**< Client is doing an Ident lookup (RFC931) */
|
|
#define CLIENT_FLAG_IDENTLOOKUPSENT 0x00000400 /**< Set if we havent writen to ident server */
|
|
#define CLIENT_FLAG_LOCALHOST 0x00000800 /**< Set for localhost clients */
|
|
#define CLIENT_FLAG_IDENTSUCCESS 0x00001000 /**< Successful ident lookup achieved */
|
|
#define CLIENT_FLAG_USEIDENT 0x00002000 /**< The allow { } block says we should use the ident (if available) */
|
|
#define CLIENT_FLAG_NEXTCALL 0x00004000 /**< Next call (don't ask...) */
|
|
#define CLIENT_FLAG_ULINE 0x00008000 /**< User/server is considered U-lined (eg: services) */
|
|
#define CLIENT_FLAG_SQUIT 0x00010000 /**< Server has been /SQUIT by an oper */
|
|
#define CLIENT_FLAG_PROTOCTL 0x00020000 /**< Received at least 1 PROTOCTL message */
|
|
#define CLIENT_FLAG_EAUTH 0x00040000 /**< Server authenticated via PROTOCTL EAUTH */
|
|
#define CLIENT_FLAG_NETINFO 0x00080000 /**< Received a NETINFO message */
|
|
#define CLIENT_FLAG_QUARANTINE 0x00100000 /**< Quarantined server (don't allow ircops on this server) */
|
|
#define CLIENT_FLAG_DCCNOTICE 0x00200000 /**< Has the user seen a notice on how to use DCCALLOW already? */
|
|
#define CLIENT_FLAG_SHUNNED 0x00400000 /**< Connection is shunned (user cannot execute any commands) */
|
|
#define CLIENT_FLAG_VIRUS 0x00800000 /**< Tagged by spamfilter as a virus */
|
|
#define CLIENT_FLAG_TLS 0x01000000 /**< Connection is using TLS */
|
|
#define CLIENT_FLAG_NOFAKELAG 0x02000000 /**< Exemption from fake lag */
|
|
#define CLIENT_FLAG_DCCBLOCK 0x04000000 /**< Block all DCC send requests */
|
|
#define CLIENT_FLAG_MAP 0x08000000 /**< Show this entry in /MAP (only used in map module) */
|
|
#define CLIENT_FLAG_PINGWARN 0x10000000 /**< Server ping warning (remote server slow with responding to PINGs) */
|
|
#define CLIENT_FLAG_NOHANDSHAKEDELAY 0x20000000 /**< No handshake delay */
|
|
#define CLIENT_FLAG_SERVER_DISCONNECT_LOGGED 0x40000000 /**< Server disconnect message is (already) logged */
|
|
#define CLIENT_FLAG_ASYNC_RPC 0x80000000 /**< Asynchronous remote RPC request - special case for rehash etc. */
|
|
|
|
/** @} */
|
|
|
|
#define OPER_SNOMASKS "+bBcdfkqsSoO"
|
|
|
|
#define SEND_UMODES (SendUmodes)
|
|
#define ALL_UMODES (AllUmodes)
|
|
/* SEND_UMODES and ALL_UMODES are now handled by umode_get/umode_lget/umode_gget -- Syzop. */
|
|
|
|
#define CLIENT_FLAG_ID (CLIENT_FLAG_USEIDENT|CLIENT_FLAG_IDENTSUCCESS)
|
|
|
|
/* PROTO_*: Server protocol extensions (acptr->local->proto).
|
|
* Note that client protocol extensions have been moved
|
|
* to the ClientCapability API which uses acptr->local->caps.
|
|
*/
|
|
#define PROTO_VL 0x000001 /* Negotiated VL protocol */
|
|
#define PROTO_VHP 0x000002 /* Send hostnames in NICKv2 even if not sethosted */
|
|
#define PROTO_CLK 0x000004 /* Send cloaked host in the NICK command (regardless of +x/-x) */
|
|
#define PROTO_MLOCK 0x000008 /* server supports MLOCK */
|
|
#define PROTO_EXTSWHOIS 0x000010 /* extended SWHOIS support */
|
|
#define PROTO_SJSBY 0x000020 /* SJOIN setby information (TS and nick) */
|
|
#define PROTO_MTAGS 0x000040 /* Support message tags and big buffers */
|
|
#define PROTO_NEXTBANS 0x000080 /* Server supports named extended bans */
|
|
|
|
/* For client capabilities: */
|
|
#define CAP_INVERT 1L
|
|
|
|
/** HasCapabilityFast() checks for a token if you know exactly which bit to check */
|
|
#define HasCapabilityFast(cptr, val) ((cptr)->local->caps & (val))
|
|
/** HasCapability() checks for a token by name and is slightly slower */
|
|
#define HasCapability(cptr, token) ((cptr)->local->caps & ClientCapabilityBit(token))
|
|
#define SetCapabilityFast(cptr, val) do { (cptr)->local->caps |= (val); } while(0)
|
|
#define ClearCapabilityFast(cptr, val) do { (cptr)->local->caps &= ~(val); } while(0)
|
|
|
|
/* Usermode and snomask macros: */
|
|
#define IsDeaf(x) ((x)->umodes & UMODE_DEAF)
|
|
#define IsOper(x) ((x)->umodes & UMODE_OPER)
|
|
#define IsInvisible(x) ((x)->umodes & UMODE_INVISIBLE)
|
|
#define IsRegNick(x) ((x)->umodes & UMODE_REGNICK)
|
|
#define IsHidden(x) ((x)->umodes & UMODE_HIDE)
|
|
#define IsSetHost(x) ((x)->umodes & UMODE_SETHOST)
|
|
#define IsHideOper(x) ((x)->umodes & UMODE_HIDEOPER)
|
|
#define SetOper(x) ((x)->umodes |= UMODE_OPER)
|
|
#define SetInvisible(x) ((x)->umodes |= UMODE_INVISIBLE)
|
|
#define SetRegNick(x) ((x)->umodes & UMODE_REGNICK)
|
|
#define SetHidden(x) ((x)->umodes |= UMODE_HIDE)
|
|
#define SetHideOper(x) ((x)->umodes |= UMODE_HIDEOPER)
|
|
#define IsSecureConnect(x) ((x)->umodes & UMODE_SECURE)
|
|
#define ClearOper(x) ((x)->umodes &= ~UMODE_OPER)
|
|
#define ClearInvisible(x) ((x)->umodes &= ~UMODE_INVISIBLE)
|
|
#define ClearHidden(x) ((x)->umodes &= ~UMODE_HIDE)
|
|
#define ClearHideOper(x) ((x)->umodes &= ~UMODE_HIDEOPER)
|
|
|
|
/* Client flags macros: to check for via IsXX(),
|
|
* to set via SetXX() and to clear the flag via ClearXX()
|
|
*/
|
|
/**
|
|
* @addtogroup ClientFlags
|
|
* @{
|
|
*/
|
|
#define IsIdentLookup(x) ((x)->flags & CLIENT_FLAG_IDENTLOOKUP) /**< Is doing Ident lookups */
|
|
#define IsClosing(x) ((x)->flags & CLIENT_FLAG_CLOSING) /**< Is closing the connection */
|
|
#define IsDCCBlock(x) ((x)->flags & CLIENT_FLAG_DCCBLOCK)
|
|
#define IsDCCNotice(x) ((x)->flags & CLIENT_FLAG_DCCNOTICE)
|
|
#define IsDead(x) ((x)->flags & CLIENT_FLAG_DEAD)
|
|
#define IsDeadSocket(x) ((x)->flags & CLIENT_FLAG_DEADSOCKET)
|
|
#define IsServerDisconnectLogged(x) ((x)->flags & CLIENT_FLAG_SERVER_DISCONNECT_LOGGED)
|
|
#define IsUseIdent(x) ((x)->flags & CLIENT_FLAG_USEIDENT)
|
|
#define IsDNSLookup(x) ((x)->flags & CLIENT_FLAG_DNSLOOKUP)
|
|
#define IsEAuth(x) ((x)->flags & CLIENT_FLAG_EAUTH)
|
|
#define IsIdentSuccess(x) ((x)->flags & CLIENT_FLAG_IDENTSUCCESS)
|
|
#define IsKilled(x) ((x)->flags & CLIENT_FLAG_KILLED)
|
|
#define IsMonitorRehash(x) ((x)->flags & CLIENT_FLAG_MONITOR_REHASH)
|
|
#define IsListening(x) ((x)->flags & CLIENT_FLAG_LISTEN)
|
|
#define IsLocalhost(x) ((x)->flags & CLIENT_FLAG_LOCALHOST)
|
|
#define IsMap(x) ((x)->flags & CLIENT_FLAG_MAP)
|
|
#define IsNextCall(x) ((x)->flags & CLIENT_FLAG_NEXTCALL)
|
|
#define IsNetInfo(x) ((x)->flags & CLIENT_FLAG_NETINFO)
|
|
#define IsNoFakeLag(x) ((x)->flags & CLIENT_FLAG_NOFAKELAG)
|
|
#define IsOutgoing(x) ((x)->flags & CLIENT_FLAG_OUTGOING)
|
|
#define IsPingSent(x) ((x)->flags & CLIENT_FLAG_PINGSENT)
|
|
#define IsPingWarning(x) ((x)->flags & CLIENT_FLAG_PINGWARN)
|
|
#define IsNoHandshakeDelay(x) ((x)->flags & CLIENT_FLAG_NOHANDSHAKEDELAY)
|
|
#define IsProtoctlReceived(x) ((x)->flags & CLIENT_FLAG_PROTOCTL)
|
|
#define IsQuarantined(x) ((x)->flags & CLIENT_FLAG_QUARANTINE)
|
|
#define IsShunned(x) ((x)->flags & CLIENT_FLAG_SHUNNED)
|
|
#define IsSQuit(x) ((x)->flags & CLIENT_FLAG_SQUIT)
|
|
#define IsTLS(x) ((x)->flags & CLIENT_FLAG_TLS)
|
|
#define IsSecure(x) ((x)->flags & CLIENT_FLAG_TLS)
|
|
#define IsULine(x) ((x)->flags & CLIENT_FLAG_ULINE)
|
|
#define IsSvsCmdOk(x) (((x)->flags & CLIENT_FLAG_ULINE) || ((iConf.limit_svscmds == LIMIT_SVSCMDS_SERVERS) && (IsServer((x)) || IsMe((x)))))
|
|
#define IsVirus(x) ((x)->flags & CLIENT_FLAG_VIRUS)
|
|
#define IsIdentLookupSent(x) ((x)->flags & CLIENT_FLAG_IDENTLOOKUPSENT)
|
|
#define IsAsyncRPC(x) ((x)->flags & CLIENT_FLAG_ASYNC_RPC)
|
|
#define SetIdentLookup(x) do { (x)->flags |= CLIENT_FLAG_IDENTLOOKUP; } while(0)
|
|
#define SetClosing(x) do { (x)->flags |= CLIENT_FLAG_CLOSING; } while(0)
|
|
#define SetDCCBlock(x) do { (x)->flags |= CLIENT_FLAG_DCCBLOCK; } while(0)
|
|
#define SetDCCNotice(x) do { (x)->flags |= CLIENT_FLAG_DCCNOTICE; } while(0)
|
|
#define SetDead(x) do { (x)->flags |= CLIENT_FLAG_DEAD; } while(0)
|
|
#define SetDeadSocket(x) do { (x)->flags |= CLIENT_FLAG_DEADSOCKET; } while(0)
|
|
#define SetServerDisconnectLogged(x) do { (x)->flags |= CLIENT_FLAG_SERVER_DISCONNECT_LOGGED; } while(0)
|
|
#define SetUseIdent(x) do { (x)->flags |= CLIENT_FLAG_USEIDENT; } while(0)
|
|
#define SetDNSLookup(x) do { (x)->flags |= CLIENT_FLAG_DNSLOOKUP; } while(0)
|
|
#define SetEAuth(x) do { (x)->flags |= CLIENT_FLAG_EAUTH; } while(0)
|
|
#define SetIdentSuccess(x) do { (x)->flags |= CLIENT_FLAG_IDENTSUCCESS; } while(0)
|
|
#define SetKilled(x) do { (x)->flags |= CLIENT_FLAG_KILLED; } while(0)
|
|
#define SetMonitorRehash(x) do { (x)->flags |= CLIENT_FLAG_MONITOR_REHASH; } while(0)
|
|
#define SetListening(x) do { (x)->flags |= CLIENT_FLAG_LISTEN; } while(0)
|
|
#define SetLocalhost(x) do { (x)->flags |= CLIENT_FLAG_LOCALHOST; } while(0)
|
|
#define SetMap(x) do { (x)->flags |= CLIENT_FLAG_MAP; } while(0)
|
|
#define SetNextCall(x) do { (x)->flags |= CLIENT_FLAG_NEXTCALL; } while(0)
|
|
#define SetNetInfo(x) do { (x)->flags |= CLIENT_FLAG_NETINFO; } while(0)
|
|
#define SetNoFakeLag(x) do { (x)->flags |= CLIENT_FLAG_NOFAKELAG; } while(0)
|
|
#define SetOutgoing(x) do { (x)->flags |= CLIENT_FLAG_OUTGOING; } while(0)
|
|
#define SetPingSent(x) do { (x)->flags |= CLIENT_FLAG_PINGSENT; } while(0)
|
|
#define SetPingWarning(x) do { (x)->flags |= CLIENT_FLAG_PINGWARN; } while(0)
|
|
#define SetNoHandshakeDelay(x) do { (x)->flags |= CLIENT_FLAG_NOHANDSHAKEDELAY; } while(0)
|
|
#define SetProtoctlReceived(x) do { (x)->flags |= CLIENT_FLAG_PROTOCTL; } while(0)
|
|
#define SetQuarantined(x) do { (x)->flags |= CLIENT_FLAG_QUARANTINE; } while(0)
|
|
#define SetShunned(x) do { (x)->flags |= CLIENT_FLAG_SHUNNED; } while(0)
|
|
#define SetSQuit(x) do { (x)->flags |= CLIENT_FLAG_SQUIT; } while(0)
|
|
#define SetTLS(x) do { (x)->flags |= CLIENT_FLAG_TLS; } while(0)
|
|
#define SetULine(x) do { (x)->flags |= CLIENT_FLAG_ULINE; } while(0)
|
|
#define SetVirus(x) do { (x)->flags |= CLIENT_FLAG_VIRUS; } while(0)
|
|
#define SetIdentLookupSent(x) do { (x)->flags |= CLIENT_FLAG_IDENTLOOKUPSENT; } while(0)
|
|
#define SetAsyncRPC(x) do { (x)->flags |= CLIENT_FLAG_ASYNC_RPC; } while(0)
|
|
#define ClearIdentLookup(x) do { (x)->flags &= ~CLIENT_FLAG_IDENTLOOKUP; } while(0)
|
|
#define ClearClosing(x) do { (x)->flags &= ~CLIENT_FLAG_CLOSING; } while(0)
|
|
#define ClearDCCBlock(x) do { (x)->flags &= ~CLIENT_FLAG_DCCBLOCK; } while(0)
|
|
#define ClearDCCNotice(x) do { (x)->flags &= ~CLIENT_FLAG_DCCNOTICE; } while(0)
|
|
#define ClearDead(x) do { (x)->flags &= ~CLIENT_FLAG_DEAD; } while(0)
|
|
#define ClearDeadSocket(x) do { (x)->flags &= ~CLIENT_FLAG_DEADSOCKET; } while(0)
|
|
#define ClearUseIdent(x) do { (x)->flags &= ~CLIENT_FLAG_USEIDENT; } while(0)
|
|
#define ClearDNSLookup(x) do { (x)->flags &= ~CLIENT_FLAG_DNSLOOKUP; } while(0)
|
|
#define ClearEAuth(x) do { (x)->flags &= ~CLIENT_FLAG_EAUTH; } while(0)
|
|
#define ClearIdentSuccess(x) do { (x)->flags &= ~CLIENT_FLAG_IDENTSUCCESS; } while(0)
|
|
#define ClearKilled(x) do { (x)->flags &= ~CLIENT_FLAG_KILLED; } while(0)
|
|
#define ClearMonitorRehash(x) do { (x)->flags &= ~CLIENT_FLAG_MONITOR_REHASH; } while(0)
|
|
#define ClearListening(x) do { (x)->flags &= ~CLIENT_FLAG_LISTEN; } while(0)
|
|
#define ClearLocalhost(x) do { (x)->flags &= ~CLIENT_FLAG_LOCALHOST; } while(0)
|
|
#define ClearMap(x) do { (x)->flags &= ~CLIENT_FLAG_MAP; } while(0)
|
|
#define ClearNextCall(x) do { (x)->flags &= ~CLIENT_FLAG_NEXTCALL; } while(0)
|
|
#define ClearNetInfo(x) do { (x)->flags &= ~CLIENT_FLAG_NETINFO; } while(0)
|
|
#define ClearNoFakeLag(x) do { (x)->flags &= ~CLIENT_FLAG_NOFAKELAG; } while(0)
|
|
#define ClearOutgoing(x) do { (x)->flags &= ~CLIENT_FLAG_OUTGOING; } while(0)
|
|
#define ClearPingSent(x) do { (x)->flags &= ~CLIENT_FLAG_PINGSENT; } while(0)
|
|
#define ClearPingWarning(x) do { (x)->flags &= ~CLIENT_FLAG_PINGWARN; } while(0)
|
|
#define ClearNoHandshakeDelay(x) do { (x)->flags &= ~CLIENT_FLAG_NOHANDSHAKEDELAY; } while(0)
|
|
#define ClearProtoctlReceived(x) do { (x)->flags &= ~CLIENT_FLAG_PROTOCTL; } while(0)
|
|
#define ClearQuarantined(x) do { (x)->flags &= ~CLIENT_FLAG_QUARANTINE; } while(0)
|
|
#define ClearShunned(x) do { (x)->flags &= ~CLIENT_FLAG_SHUNNED; } while(0)
|
|
#define ClearSQuit(x) do { (x)->flags &= ~CLIENT_FLAG_SQUIT; } while(0)
|
|
#define ClearTLS(x) do { (x)->flags &= ~CLIENT_FLAG_TLS; } while(0)
|
|
#define ClearULine(x) do { (x)->flags &= ~CLIENT_FLAG_ULINE; } while(0)
|
|
#define ClearVirus(x) do { (x)->flags &= ~CLIENT_FLAG_VIRUS; } while(0)
|
|
#define ClearIdentLookupSent(x) do { (x)->flags &= ~CLIENT_FLAG_IDENTLOOKUPSENT; } while(0)
|
|
#define ClearAsyncRPC(x) do { (x)->flags &= ~CLIENT_FLAG_ASYNC_RPC; } while(0)
|
|
/** @} */
|
|
|
|
#define IsIPV6(x) ((x)->local->socket_type == SOCKET_TYPE_IPV6)
|
|
#define IsUnixSocket(x) ((x)->local->socket_type == SOCKET_TYPE_UNIX)
|
|
#define SetIPV6(x) do { (x)->local->socket_type = SOCKET_TYPE_IPV6; } while(0)
|
|
#define SetUnixSocket(x) do { (x)->local->socket_type = SOCKET_TYPE_UNIX; } while(0)
|
|
|
|
/* Others that access client structs: */
|
|
#define IsNotSpoof(x) ((x)->local->nospoof == 0)
|
|
#define GetHost(x) (IsHidden(x) ? (x)->user->virthost : (x)->user->realhost)
|
|
#define GetIP(x) (x->ip ? x->ip : "255.255.255.255")
|
|
#define IsLoggedIn(x) (x->user && (*x->user->account != '*') && !isdigit(*x->user->account)) /**< Logged into services */
|
|
#define IsSynched(x) (x->server->flags.synced)
|
|
#define IsServerSent(x) (x->server && x->server->flags.server_sent)
|
|
|
|
/* And more that access client stuff - but actually modularized */
|
|
#define GetReputation(client) (moddata_client_get(client, "reputation") ? atoi(moddata_client_get(client, "reputation")) : 0) /**< Get reputation value for a client */
|
|
|
|
/* PROTOCTL (Server protocol) stuff */
|
|
#ifndef DEBUGMODE
|
|
#define CHECKSERVERPROTO(x,y) (((x)->local->proto & y) == y)
|
|
#else
|
|
#define CHECKSERVERPROTO(x,y) (checkprotoflags(x, y, __FILE__, __LINE__))
|
|
#endif
|
|
|
|
#define SupportVL(x) (CHECKSERVERPROTO(x, PROTO_VL))
|
|
#define SupportSJSBY(x) (CHECKSERVERPROTO(x, PROTO_SJSBY))
|
|
#define SupportVHP(x) (CHECKSERVERPROTO(x, PROTO_VHP))
|
|
#define SupportCLK(x) (CHECKSERVERPROTO(x, PROTO_CLK))
|
|
#define SupportMTAGS(x) (CHECKSERVERPROTO(x, PROTO_MTAGS))
|
|
#define SupportNEXTBANS(x) (CHECKSERVERPROTO(x, PROTO_NEXTBANS))
|
|
|
|
#define SetVL(x) ((x)->local->proto |= PROTO_VL)
|
|
#define SetSJSBY(x) ((x)->local->proto |= PROTO_SJSBY)
|
|
#define SetVHP(x) ((x)->local->proto |= PROTO_VHP)
|
|
#define SetCLK(x) ((x)->local->proto |= PROTO_CLK)
|
|
#define SetMTAGS(x) ((x)->local->proto |= PROTO_MTAGS)
|
|
#define SetNEXTBANS(x) ((x)->local->proto |= PROTO_NEXTBANS)
|
|
|
|
/* Dcc deny types (see src/s_extra.c) */
|
|
#define DCCDENY_HARD 0
|
|
#define DCCDENY_SOFT 1
|
|
|
|
/* Linked list dcc flags */
|
|
#define DCC_LINK_ME 1 /* My dcc allow */
|
|
#define DCC_LINK_REMOTE 2 /* I need to remove dccallows from these clients when I die */
|
|
|
|
/** Union for moddata objects */
|
|
typedef union ModData ModData;
|
|
union ModData
|
|
{
|
|
int i;
|
|
long l;
|
|
long long ll;
|
|
char *str;
|
|
void *ptr;
|
|
};
|
|
|
|
#ifndef _WIN32
|
|
#define CHECK_LIST_ENTRY(list) if (offsetof(typeof(*list),prev) != offsetof(ListStruct,prev)) \
|
|
{ \
|
|
unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION", NULL, \
|
|
"[BUG] $file:$line: List operation on struct with incorrect order ($error_details)", \
|
|
log_data_string("error_details", "->prev must be 1st struct member"), \
|
|
log_data_string("file", __FILE__), \
|
|
log_data_integer("line", __LINE__)); \
|
|
abort(); \
|
|
} \
|
|
if (offsetof(typeof(*list),next) != offsetof(ListStruct,next)) \
|
|
{ \
|
|
unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION", NULL, \
|
|
"[BUG] $file:$line: List operation on struct with incorrect order ($error_details)", \
|
|
log_data_string("error_details", "->next must be 2nd struct member"), \
|
|
log_data_string("file", __FILE__), \
|
|
log_data_integer("line", __LINE__)); \
|
|
abort(); \
|
|
}
|
|
#else
|
|
#define CHECK_LIST_ENTRY(list) /* not available on Windows, typeof() not reliable */
|
|
#endif
|
|
|
|
#ifndef _WIN32
|
|
#define CHECK_PRIO_LIST_ENTRY(list) if (offsetof(typeof(*list),prev) != offsetof(ListStructPrio,prev)) \
|
|
{ \
|
|
unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION", NULL, \
|
|
"[BUG] $file:$line: List operation on struct with incorrect order ($error_details)", \
|
|
log_data_string("error_details", "->prev must be 1st struct member"), \
|
|
log_data_string("file", __FILE__), \
|
|
log_data_integer("line", __LINE__)); \
|
|
abort(); \
|
|
} \
|
|
if (offsetof(typeof(*list),next) != offsetof(ListStructPrio,next)) \
|
|
{ \
|
|
unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION", NULL, \
|
|
"[BUG] $file:$line: List operation on struct with incorrect order ($error_details)", \
|
|
log_data_string("error_details", "->next must be 2nd struct member"), \
|
|
log_data_string("file", __FILE__), \
|
|
log_data_integer("line", __LINE__)); \
|
|
abort(); \
|
|
} \
|
|
if (offsetof(typeof(*list),priority) != offsetof(ListStructPrio,priority)) \
|
|
{ \
|
|
unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION", NULL, \
|
|
"[BUG] $file:$line: List operation on struct with incorrect order ($error_details)", \
|
|
log_data_string("error_details", "->priority must be 3rd struct member"), \
|
|
log_data_string("file", __FILE__), \
|
|
log_data_integer("line", __LINE__)); \
|
|
abort(); \
|
|
}
|
|
#else
|
|
#define CHECK_PRIO_LIST_ENTRY(list) /* not available on Windows, typeof() not reliable */
|
|
#endif
|
|
|
|
#define CHECK_NULL_LIST_ITEM(item) if ((item)->prev || (item)->next) \
|
|
{ \
|
|
unreal_log(ULOG_FATAL, "main", "BUG_LIST_OPERATION_DOUBLE_ADD", NULL, \
|
|
"[BUG] $file:$line: List operation on item with non-NULL 'prev' or 'next' -- are you adding to a list twice?", \
|
|
log_data_string("file", __FILE__), \
|
|
log_data_integer("line", __LINE__)); \
|
|
abort(); \
|
|
}
|
|
|
|
/** These are the generic list functions that are used all around in UnrealIRCd.
|
|
* @defgroup ListFunctions List functions
|
|
* @{
|
|
*/
|
|
|
|
/** Generic linked list HEAD */
|
|
struct ListStruct {
|
|
ListStruct *prev, *next;
|
|
};
|
|
|
|
/** Generic linked list HEAD with priority */
|
|
struct ListStructPrio {
|
|
ListStructPrio *prev, *next;
|
|
int priority;
|
|
};
|
|
|
|
/** Add an item to a standard linked list (in the front)
|
|
*/
|
|
#define AddListItem(item,list) do { \
|
|
CHECK_LIST_ENTRY(list) \
|
|
CHECK_LIST_ENTRY(item) \
|
|
CHECK_NULL_LIST_ITEM(item) \
|
|
add_ListItem((ListStruct *)item, (ListStruct **)&list); \
|
|
} while(0)
|
|
|
|
/** Append an item to a standard linked list (at the back)
|
|
*/
|
|
#define AppendListItem(item,list) do { \
|
|
CHECK_LIST_ENTRY(list) \
|
|
CHECK_LIST_ENTRY(item) \
|
|
CHECK_NULL_LIST_ITEM(item) \
|
|
append_ListItem((ListStruct *)item, (ListStruct **)&list); \
|
|
} while(0)
|
|
|
|
/** Delete an item from a standard linked list
|
|
*/
|
|
#define DelListItem(item,list) do { \
|
|
CHECK_LIST_ENTRY(list) \
|
|
CHECK_LIST_ENTRY(item) \
|
|
del_ListItem((ListStruct *)item, (ListStruct **)&list); \
|
|
} while(0)
|
|
|
|
/** Add an item to a standard linked list - UNCHECKED function, only use if absolutely necessary!
|
|
*/
|
|
#define AddListItemUnchecked(item,list) add_ListItem((ListStruct *)item, (ListStruct **)&list)
|
|
/** Append an item to a standard linked list - UNCHECKED function, only use if absolutely necessary!
|
|
*/
|
|
#define AppendListItemUnchecked(item,list) append_ListItem((ListStruct *)item, (ListStruct **)&list)
|
|
/** Delete an item from a standard linked list - UNCHECKED function, only use if absolutely necessary!
|
|
*/
|
|
#define DelListItemUnchecked(item,list) del_ListItem((ListStruct *)item, (ListStruct **)&list)
|
|
|
|
#define AddListItemPrio(item,list,prio) do { \
|
|
CHECK_PRIO_LIST_ENTRY(list) \
|
|
CHECK_PRIO_LIST_ENTRY(item) \
|
|
CHECK_NULL_LIST_ITEM(item) \
|
|
item->priority = prio; \
|
|
add_ListItemPrio((ListStructPrio *)item, (ListStructPrio **)&list, prio); \
|
|
} while(0)
|
|
|
|
#define DelListItemPrio(item,list,prio) do { \
|
|
CHECK_PRIO_LIST_ENTRY(list) \
|
|
CHECK_PRIO_LIST_ENTRY(item) \
|
|
del_ListItem((ListStruct *)item, (ListStruct **)&list); \
|
|
} while(0)
|
|
|
|
typedef struct NameList NameList;
|
|
/** Generic linked list where each entry has a name which you can use.
|
|
* Use this if you simply want to have a list of entries
|
|
* that only have a name and no other properties.
|
|
*
|
|
* Use the following functions to add, find and delete entries:
|
|
* add_name_list(), find_name_list(), del_name_list(), free_entire_name_list()
|
|
*/
|
|
struct NameList {
|
|
NameList *prev, *next;
|
|
char name[1];
|
|
};
|
|
|
|
/** Free an entire NameList */
|
|
#define free_entire_name_list(list) do { _free_entire_name_list(list); list = NULL; } while(0)
|
|
/** Add an entry to a NameList */
|
|
#define add_name_list(list, str) _add_name_list(&list, str)
|
|
/** Delete an entry from a NameList - AND free it */
|
|
#define del_name_list(list, str) _del_name_list(&list, str)
|
|
|
|
extern void unreal_add_names(NameList **n, ConfigEntry *ce);
|
|
|
|
/** @} */
|
|
|
|
typedef struct MultiLine MultiLine;
|
|
/** Multi-line list.
|
|
* @see addmultiline(), freemultiline(), sendnotice_multiline()
|
|
*/
|
|
struct MultiLine {
|
|
MultiLine *prev, *next;
|
|
char *line;
|
|
};
|
|
|
|
struct MOTDFile
|
|
{
|
|
struct MOTDLine *lines;
|
|
struct tm last_modified; /* store the last modification time */
|
|
};
|
|
|
|
struct MOTDLine {
|
|
char *line;
|
|
struct MOTDLine *next;
|
|
};
|
|
|
|
/** Current status of configuration in memory (what stage are we in..) */
|
|
typedef enum ConfigStatus {
|
|
CONFIG_STATUS_NONE = 0, /**< Config files have not been parsed yet */
|
|
CONFIG_STATUS_TEST = 1, /**< Currently running MOD_TEST() */
|
|
CONFIG_STATUS_POSTTEST = 2, /**< Currently running post_config_test hooks */
|
|
CONFIG_STATUS_PRE_INIT = 3, /**< In-between */
|
|
CONFIG_STATUS_INIT = 4, /**< Currently running MOD_INIT() */
|
|
CONFIG_STATUS_RUN_CONFIG = 5, /**< Currently running CONFIG_RUN hooks */
|
|
CONFIG_STATUS_LOAD = 6, /**< Currently running MOD_LOAD() */
|
|
CONFIG_STATUS_POSTLOAD = 7, /**< Doing post-load stuff like activating listeners */
|
|
CONFIG_STATUS_COMPLETE = 8, /**< Load or rehash complete */
|
|
CONFIG_STATUS_ROLLBACK = 99, /**< Configuration failed, rolling back changes */
|
|
} ConfigStatus;
|
|
|
|
struct LoopStruct {
|
|
unsigned do_garbage_collect : 1;
|
|
unsigned config_test : 1;
|
|
unsigned booted : 1;
|
|
unsigned forked : 1;
|
|
unsigned do_bancheck : 1; /* perform *line bancheck? */
|
|
unsigned do_bancheck_spamf_user : 1; /* perform 'user' spamfilter bancheck */
|
|
unsigned do_bancheck_spamf_away : 1; /* perform 'away' spamfilter bancheck */
|
|
unsigned terminating : 1;
|
|
unsigned config_load_failed : 1;
|
|
unsigned rehash_download_busy : 1; /* don't return "all downloads complete", needed for race condition */
|
|
unsigned tainted : 1;
|
|
int rehashing;
|
|
ConfigStatus config_status;
|
|
Client *rehash_save_client;
|
|
void (*boot_function)();
|
|
};
|
|
|
|
/** Matching types for Match.type */
|
|
typedef enum {
|
|
MATCH_SIMPLE=1, /**< Simple pattern with * and ? */
|
|
MATCH_PCRE_REGEX=2, /**< PCRE2 Perl-like regex (new) */
|
|
} MatchType;
|
|
|
|
/** Match struct, which allows various matching styles, see MATCH_* */
|
|
typedef struct Match {
|
|
char *str; /**< Text of the glob/regex/whatever. Always set. */
|
|
MatchType type;
|
|
union {
|
|
pcre2_code *pcre2_expr; /**< PCRE2 Perl-like Regex */
|
|
} ext;
|
|
} Match;
|
|
|
|
typedef struct Whowas {
|
|
int hashv;
|
|
char *name;
|
|
char *username;
|
|
char *hostname;
|
|
char *virthost;
|
|
char *ip;
|
|
char *servername;
|
|
char *realname;
|
|
char *account;
|
|
long umodes;
|
|
time_t logon;
|
|
time_t logoff;
|
|
time_t connected_since;
|
|
WhoWasEvent event;
|
|
struct Client *online; /* Pointer to new nickname for chasing or NULL */
|
|
struct Whowas *next; /* for hash table... */
|
|
struct Whowas *prev; /* for hash table... */
|
|
struct Whowas *cnext; /* for client struct linked list */
|
|
struct Whowas *cprev; /* for client struct linked list */
|
|
} WhoWas;
|
|
|
|
typedef struct SWhois SWhois;
|
|
struct SWhois {
|
|
SWhois *prev, *next;
|
|
int priority;
|
|
char *line;
|
|
char *setby;
|
|
};
|
|
|
|
/** The command API - used by modules and the core to add commands, overrides, etc.
|
|
* See also https://www.unrealircd.org/docs/Dev:Command_API for a higher level overview and example.
|
|
* @defgroup CommandAPI Command API
|
|
* @{
|
|
*/
|
|
/** Command can be called by unregistered users (still in handshake) */
|
|
#define CMD_UNREGISTERED 0x0001
|
|
/** Command can be called by users (either directly connected, or remote) */
|
|
#define CMD_USER 0x0002
|
|
/** Command can be called by servers */
|
|
#define CMD_SERVER 0x0004
|
|
/** Command can be used by shunned users (only very few commands need this) */
|
|
#define CMD_SHUN 0x0008
|
|
/** Command will NOT add fake lag (extremely rare, use with care) */
|
|
#define CMD_NOLAG 0x0010
|
|
/** Command is actually an alias */
|
|
#define CMD_ALIAS 0x0020
|
|
/** Command will reset the idle time (only for PRIVMSG) */
|
|
#define CMD_RESETIDLE 0x0040
|
|
/** Command can be used by virus tagged users (only very few commands) */
|
|
#define CMD_VIRUS 0x0080
|
|
/** Command requires IRCOp privileges */
|
|
#define CMD_OPER 0x0200
|
|
/** Command is for control channel only (unrealircd.ctl socket) */
|
|
#define CMD_CONTROL 0x0400
|
|
|
|
/** Command function - used by all command handlers.
|
|
* This is used in the code like <pre>CMD_FUNC(cmd_yourcmd)</pre> as a function definition.
|
|
* It allows UnrealIRCd devs to change the parameters in the function without
|
|
* (necessarily) breaking your code.
|
|
* @param client The client
|
|
* @param recv_mtags Received message tags for this command.
|
|
* @param parc Parameter count *plus* 1.
|
|
* @param parv Parameter values.
|
|
* @note Slightly confusing, but parc will be 2 if 1 parameter was provided.
|
|
* It is two because parv will still have 2 elements, parv[1] will be your first parameter,
|
|
* and parv[2] will be NULL.
|
|
* Note that reading parv[parc] and beyond is OUT OF BOUNDS and will cause a crash.
|
|
* E.g. parv[3] in the above example is out of bounds.
|
|
*/
|
|
#define CMD_FUNC(x) void (x) (Client *client, MessageTag *recv_mtags, int parc, const char *parv[])
|
|
|
|
/** Call a command function - can be useful if you are calling another command function in your own module.
|
|
* For example in cmd_nick() we call cmd_nick_local() for local functions,
|
|
* and then we can just use CALL_CMD_FUNC(cmd_nick_local); and don't have
|
|
* to bother with passing the right command arguments. Which is nice because
|
|
* command arguments may change in future UnrealIRCd versions.
|
|
*/
|
|
#define CALL_CMD_FUNC(x) (x)(client, recv_mtags, parc, parv)
|
|
|
|
/** @} */
|
|
|
|
/** Command override function - used by all command override handlers.
|
|
* This is used in the code like <pre>CMD_OVERRIDE_FUNC(ovr_somecmd)</pre> as a function definition.
|
|
* @param ovr The command override structure.
|
|
* @param cptr The client direction pointer.
|
|
* @param client The source client pointer (you usually need this one).
|
|
* @param recv_mtags Received message tags for this command.
|
|
* @param parc Parameter count *plus* 1.
|
|
* @param parv Parameter values.
|
|
* @note Slightly confusing, but parc will be 2 if 1 parameter was provided.
|
|
* It is two because parv will still have 2 elements, parv[1] will be your first parameter,
|
|
* and parv[2] will be NULL.
|
|
* Note that reading parv[parc] and beyond is OUT OF BOUNDS and will cause a crash.
|
|
* E.g. parv[3] in the above example.
|
|
*/
|
|
#define CMD_OVERRIDE_FUNC(x) void (x)(CommandOverride *ovr, Client *client, MessageTag *recv_mtags, int parc, const char *parv[])
|
|
|
|
|
|
|
|
typedef void (*CmdFunc)(Client *client, MessageTag *mtags, int parc, const char *parv[]);
|
|
typedef void (*AliasCmdFunc)(Client *client, MessageTag *mtags, int parc, const char *parv[], const char *cmd);
|
|
typedef void (*OverrideCmdFunc)(CommandOverride *ovr, Client *client, MessageTag *mtags, int parc, const char *parv[]);
|
|
|
|
#include <sodium.h>
|
|
|
|
/* This is the 'chunk size', the size of encryption blocks.
|
|
* We choose 4K here since that is a decent amount as of 2021 and
|
|
* more would not benefit performance anyway.
|
|
* Note that you cannot change this value easily afterwards
|
|
* (you cannot read files with a different chunk size).
|
|
*/
|
|
#define UNREALDB_CRYPT_FILE_CHUNK_SIZE 4096
|
|
|
|
/** The salt length. Don't change. */
|
|
#define UNREALDB_SALT_LEN 16
|
|
|
|
/** Database modes of operation (read or write)
|
|
* @ingroup UnrealDBFunctions
|
|
*/
|
|
typedef enum UnrealDBMode {
|
|
UNREALDB_MODE_READ = 0,
|
|
UNREALDB_MODE_WRITE = 1
|
|
} UnrealDBMode;
|
|
|
|
typedef enum UnrealDBCipher {
|
|
UNREALDB_CIPHER_XCHACHA20 = 0x0001
|
|
} UnrealDBCipher;
|
|
|
|
typedef enum UnrealDBKDF {
|
|
UNREALDB_KDF_ARGON2ID = 0x0001
|
|
} UnrealDBKDF;
|
|
|
|
/** Database configuration for a particular file */
|
|
typedef struct UnrealDBConfig {
|
|
uint16_t kdf; /**< Key derivation function (always 0x01) */
|
|
uint16_t t_cost; /**< Time cost (number of rounds) */
|
|
uint16_t m_cost; /**< Memory cost (in number of bitshifts, eg 15 means 1<<15=32M) */
|
|
uint16_t p_cost; /**< Parallel cost (number of concurrent threads) */
|
|
uint16_t saltlen; /**< Length of the salt (normally UNREALDB_SALT_LEN) */
|
|
char *salt; /**< Salt */
|
|
uint16_t cipher; /**< Encryption cipher (always 0x01) */
|
|
uint16_t keylen; /**< Key length */
|
|
char *key; /**< The key used for encryption/decryption */
|
|
} UnrealDBConfig;
|
|
|
|
/** Error codes returned by @ref UnrealDBFunctions
|
|
* @ingroup UnrealDBFunctions
|
|
*/
|
|
typedef enum UnrealDBError {
|
|
UNREALDB_ERROR_SUCCESS = 0, /**< Success, not an error */
|
|
UNREALDB_ERROR_FILENOTFOUND = 1, /**< File does not exist */
|
|
UNREALDB_ERROR_CRYPTED = 2, /**< File is crypted but no password provided */
|
|
UNREALDB_ERROR_NOTCRYPTED = 3, /**< File is not crypted and a password was provided */
|
|
UNREALDB_ERROR_HEADER = 4, /**< Header is corrupt, invalid or unknown format */
|
|
UNREALDB_ERROR_SECRET = 5, /**< Invalid secret { } block provided - either does not exist or does not meet requirements */
|
|
UNREALDB_ERROR_PASSWORD = 6, /**< Invalid password provided */
|
|
UNREALDB_ERROR_IO = 7, /**< I/O error */
|
|
UNREALDB_ERROR_API = 8, /**< API call violation, eg requesting to write on a file opened for reading */
|
|
UNREALDB_ERROR_INTERNAL = 9, /**< Internal error, eg crypto routine returned something unexpected */
|
|
} UnrealDBError;
|
|
|
|
/** Database handle
|
|
* This is returned by unrealdb_open() and used by all other @ref UnrealDBFunctions
|
|
* @ingroup UnrealDBFunctions
|
|
*/
|
|
typedef struct UnrealDB {
|
|
FILE *fd; /**< File descriptor */
|
|
UnrealDBMode mode; /**< UNREALDB_MODE_READ / UNREALDB_MODE_WRITE */
|
|
int crypted; /**< Are we doing any encryption or just plaintext? */
|
|
uint64_t creationtime; /**< When this file was created/updates */
|
|
crypto_secretstream_xchacha20poly1305_state st; /**< Internal state for crypto engine */
|
|
char buf[UNREALDB_CRYPT_FILE_CHUNK_SIZE]; /**< Buffer used for reading/writing */
|
|
int buflen; /**< Length of current data in buffer */
|
|
UnrealDBError error_code; /**< Last error code. Whenever this happens we will set this, never overwrite, and block further I/O */
|
|
char *error_string; /**< Error string upon failure */
|
|
UnrealDBConfig *config; /**< Config */
|
|
} UnrealDB;
|
|
|
|
/** Used for speeding up reading/writing of DBs (so we don't have to run argon2 repeatedly) */
|
|
typedef struct SecretCache SecretCache;
|
|
struct SecretCache {
|
|
SecretCache *prev, *next;
|
|
UnrealDBConfig *config;
|
|
time_t cache_hit;
|
|
};
|
|
|
|
/** Used for storing secret { } blocks */
|
|
struct Secret {
|
|
Secret *prev, *next;
|
|
char *name;
|
|
char *password;
|
|
SecretCache *cache;
|
|
};
|
|
|
|
|
|
/* tkl:
|
|
* TKL_KILL|TKL_GLOBAL = Global K-Line (GLINE)
|
|
* TKL_ZAP|TKL_GLOBAL = Global Z-Line (ZLINE)
|
|
* TKL_KILL = Local K-Line
|
|
* TKL_ZAP = Local Z-Line
|
|
*/
|
|
#define TKL_KILL 0x00000001
|
|
#define TKL_ZAP 0x00000002
|
|
#define TKL_GLOBAL 0x00000004
|
|
#define TKL_SHUN 0x00000008
|
|
#define TKL_SPAMF 0x00000020
|
|
#define TKL_NAME 0x00000040
|
|
#define TKL_EXCEPTION 0x00000080
|
|
/* these are not real tkl types, but only used for exceptions: */
|
|
#define TKL_BLACKLIST 0x0001000
|
|
#define TKL_CONNECT_FLOOD 0x0002000
|
|
#define TKL_MAXPERIP 0x0004000
|
|
#define TKL_HANDSHAKE_DATA_FLOOD 0x0008000
|
|
#define TKL_ANTIRANDOM 0x0010000
|
|
#define TKL_ANTIMIXEDUTF8 0x0020000
|
|
#define TKL_BAN_VERSION 0x0040000
|
|
|
|
#define TKLIsServerBan(tkl) ((tkl)->type & (TKL_KILL|TKL_ZAP|TKL_SHUN))
|
|
#define TKLIsServerBanType(tpe) ((tpe) & (TKL_KILL|TKL_ZAP|TKL_SHUN))
|
|
#define TKLIsSpamfilter(tkl) ((tkl)->type & TKL_SPAMF)
|
|
#define TKLIsSpamfilterType(tpe) ((tpe) & TKL_SPAMF)
|
|
#define TKLIsNameBan(tkl) ((tkl)->type & TKL_NAME)
|
|
#define TKLIsNameBanType(tpe) ((tpe) & TKL_NAME)
|
|
#define TKLIsBanException(tkl) ((tkl)->type & TKL_EXCEPTION)
|
|
#define TKLIsBanExceptionType(tpe) ((tpe) & TKL_EXCEPTION)
|
|
|
|
#define SPAMF_CHANMSG 0x0001 /* c */
|
|
#define SPAMF_USERMSG 0x0002 /* p */
|
|
#define SPAMF_USERNOTICE 0x0004 /* n */
|
|
#define SPAMF_CHANNOTICE 0x0008 /* N */
|
|
#define SPAMF_PART 0x0010 /* P */
|
|
#define SPAMF_QUIT 0x0020 /* q */
|
|
#define SPAMF_DCC 0x0040 /* d */
|
|
#define SPAMF_USER 0x0080 /* u */
|
|
#define SPAMF_AWAY 0x0100 /* a */
|
|
#define SPAMF_TOPIC 0x0200 /* t */
|
|
#define SPAMF_MTAG 0x0400 /* m */
|
|
|
|
/* Other flags only for function calls: */
|
|
#define SPAMFLAG_NOWARN 0x0001
|
|
|
|
/* Ban actions. These must be ordered by severity (!) */
|
|
typedef enum BanAction {
|
|
BAN_ACT_GZLINE =1100,
|
|
BAN_ACT_GLINE =1000,
|
|
BAN_ACT_SOFT_GLINE = 950,
|
|
BAN_ACT_ZLINE = 900,
|
|
BAN_ACT_KLINE = 800,
|
|
BAN_ACT_SOFT_KLINE = 850,
|
|
BAN_ACT_SHUN = 700,
|
|
BAN_ACT_SOFT_SHUN = 650,
|
|
BAN_ACT_KILL = 600,
|
|
BAN_ACT_SOFT_KILL = 550,
|
|
BAN_ACT_TEMPSHUN = 500,
|
|
BAN_ACT_SOFT_TEMPSHUN = 450,
|
|
BAN_ACT_VIRUSCHAN = 400,
|
|
BAN_ACT_SOFT_VIRUSCHAN = 350,
|
|
BAN_ACT_DCCBLOCK = 300,
|
|
BAN_ACT_SOFT_DCCBLOCK = 250,
|
|
BAN_ACT_BLOCK = 200,
|
|
BAN_ACT_SOFT_BLOCK = 150,
|
|
BAN_ACT_WARN = 100,
|
|
BAN_ACT_SOFT_WARN = 50,
|
|
} BanAction;
|
|
|
|
#define IsSoftBanAction(x) ((x == BAN_ACT_SOFT_GLINE) || (x == BAN_ACT_SOFT_KLINE) || \
|
|
(x == BAN_ACT_SOFT_SHUN) || (x == BAN_ACT_SOFT_KILL) || \
|
|
(x == BAN_ACT_SOFT_TEMPSHUN) || (x == BAN_ACT_SOFT_VIRUSCHAN) || \
|
|
(x == BAN_ACT_SOFT_DCCBLOCK) || (x == BAN_ACT_SOFT_BLOCK) || \
|
|
(x == BAN_ACT_SOFT_WARN))
|
|
|
|
|
|
/** Server ban sub-struct of TKL entry (KLINE/GLINE/ZLINE/GZLINE/SHUN) */
|
|
struct ServerBan {
|
|
char *usermask; /**< User mask */
|
|
char *hostmask; /**< Host mask */
|
|
unsigned short subtype; /**< See TKL_SUBTYPE_* */
|
|
char *reason; /**< Reason */
|
|
};
|
|
|
|
/* Name ban sub-struct of TKL entry (QLINE) */
|
|
struct NameBan {
|
|
char hold; /**< nickname hold is used by services */
|
|
char *name; /**< the nick or channel that is banned */
|
|
char *reason; /**< Reason */
|
|
};
|
|
|
|
/** Spamfilter sub-struct of TKL entry (Spamfilter) */
|
|
struct Spamfilter {
|
|
unsigned short target;
|
|
BanAction action; /**< Ban action, see BAN_ACT* */
|
|
Match *match; /**< Spamfilter matcher */
|
|
char *tkl_reason; /**< Reason to use for bans placed by this spamfilter, escaped by unreal_encodespace(). */
|
|
time_t tkl_duration; /**< Duration of bans placed by this spamfilter */
|
|
};
|
|
|
|
/** Ban exception sub-struct of TKL entry (ELINE) */
|
|
struct BanException {
|
|
char *usermask; /**< User mask */
|
|
char *hostmask; /**< Host mask */
|
|
SecurityGroup *match; /**< Security group (for config file items only) */
|
|
unsigned short subtype; /**< See TKL_SUBTYPE_* */
|
|
char *bantypes; /**< Exception types */
|
|
char *reason; /**< Reason */
|
|
};
|
|
|
|
|
|
#define TKL_SUBTYPE_NONE 0x0000
|
|
#define TKL_SUBTYPE_SOFT 0x0001 /* (require SASL) */
|
|
|
|
#define TKL_FLAG_CONFIG 0x0001 /* Entry from configuration file. Cannot be removed by using commands. */
|
|
|
|
/** A TKL entry, such as a KLINE, GLINE, Spamfilter, QLINE, Exception, .. */
|
|
struct TKL {
|
|
TKL *prev, *next;
|
|
unsigned int type; /**< TKL type. One of TKL_*, such as TKL_KILL|TKL_GLOBAL for gline */
|
|
unsigned short flags; /**< One of TKL_FLAG_*, such as TKL_FLAG_CONFIG */
|
|
char *set_by; /**< By who was this entry added */
|
|
time_t set_at; /**< When this entry was added */
|
|
time_t expire_at; /**< When this entry will expire */
|
|
union {
|
|
Spamfilter *spamfilter;
|
|
ServerBan *serverban;
|
|
NameBan *nameban;
|
|
BanException *banexception;
|
|
} ptr;
|
|
};
|
|
|
|
/** A spamfilter except entry */
|
|
struct SpamExcept {
|
|
SpamExcept *prev, *next;
|
|
char name[1];
|
|
};
|
|
|
|
/** IRC Counts, used for /LUSERS */
|
|
typedef struct IRCCounts IRCCounts;
|
|
struct IRCCounts {
|
|
int clients; /* total */
|
|
int invisible; /* invisible */
|
|
int servers; /* servers */
|
|
int operators; /* operators */
|
|
int unknown; /* unknown local connections */
|
|
int channels; /* channels */
|
|
int me_clients; /* my clients */
|
|
int me_servers; /* my servers */
|
|
int me_max; /* local max */
|
|
int global_max; /* global max */
|
|
};
|
|
|
|
/** The /LUSERS stats information */
|
|
extern MODVAR IRCCounts irccounts;
|
|
|
|
typedef struct NameValue NameValue;
|
|
/** Name and value list used in a static array, such as in conf.c */
|
|
struct NameValue
|
|
{
|
|
long value;
|
|
char *name;
|
|
};
|
|
|
|
/** Name and value list used in dynamic linked lists */
|
|
typedef struct NameValueList NameValueList;
|
|
struct NameValueList {
|
|
NameValueList *prev, *next;
|
|
char *name;
|
|
char *value;
|
|
};
|
|
|
|
typedef struct NameValuePrioList NameValuePrioList;
|
|
struct NameValuePrioList {
|
|
NameValuePrioList *prev, *next;
|
|
int priority;
|
|
char *name;
|
|
char *value;
|
|
};
|
|
|
|
#include "modules.h"
|
|
|
|
/** A "real" command (internal interface, not for modules) */
|
|
struct RealCommand {
|
|
RealCommand *prev, *next;
|
|
char *cmd;
|
|
CmdFunc func;
|
|
AliasCmdFunc aliasfunc;
|
|
int flags;
|
|
unsigned int count;
|
|
unsigned parameters : 5;
|
|
unsigned long bytes;
|
|
Module *owner;
|
|
RealCommand *friend; /* cmd if token, token if cmd */
|
|
CommandOverride *overriders;
|
|
#ifdef DEBUGMODE
|
|
unsigned long lticks;
|
|
unsigned long rticks;
|
|
#endif
|
|
};
|
|
|
|
/** A command override */
|
|
struct CommandOverride {
|
|
CommandOverride *prev, *next;
|
|
int priority;
|
|
Module *owner;
|
|
RealCommand *command;
|
|
OverrideCmdFunc func;
|
|
};
|
|
|
|
extern MODVAR Umode *usermodes;
|
|
extern MODVAR Cmode *channelmodes;
|
|
|
|
extern Umode *UmodeAdd(Module *module, char ch, int options, int unset_on_deoper, int (*allowed)(Client *client, int what), long *mode);
|
|
extern void UmodeDel(Umode *umode);
|
|
|
|
extern Cmode *CmodeAdd(Module *reserved, CmodeInfo req, Cmode_t *mode);
|
|
extern void CmodeDel(Cmode *cmode);
|
|
|
|
extern void moddata_init(void);
|
|
extern ModDataInfo *ModDataAdd(Module *module, ModDataInfo req);
|
|
extern void ModDataDel(ModDataInfo *md);
|
|
extern void unload_all_unused_moddata(void);
|
|
|
|
#define LISTENER_NORMAL 0x000001
|
|
#define LISTENER_CLIENTSONLY 0x000002
|
|
#define LISTENER_SERVERSONLY 0x000004
|
|
#define LISTENER_TLS 0x000010
|
|
#define LISTENER_BOUND 0x000020
|
|
#define LISTENER_DEFER_ACCEPT 0x000040
|
|
#define LISTENER_CONTROL 0x000080 /**< Control channel */
|
|
#define LISTENER_NO_CHECK_CONNECT_FLOOD 0x000100 /**< Don't check for connect-flood and max-unknown-connections-per-ip (eg for RPC) */
|
|
#define LISTENER_NO_CHECK_ZLINED 0x000200 /**< Don't check for zlines */
|
|
|
|
#define IsServersOnlyListener(x) ((x) && ((x)->options & LISTENER_SERVERSONLY))
|
|
|
|
#define CONNECT_TLS 0x000001
|
|
#define CONNECT_AUTO 0x000002
|
|
#define CONNECT_QUARANTINE 0x000004
|
|
#define CONNECT_INSECURE 0x000008
|
|
|
|
#define TLSFLAG_FAILIFNOCERT 0x0001
|
|
#define TLSFLAG_NOSTARTTLS 0x0002
|
|
#define TLSFLAG_DISABLECLIENTCERT 0x0004
|
|
|
|
/** Flood counters for local clients */
|
|
typedef struct FloodCounter {
|
|
int count;
|
|
long t;
|
|
} FloodCounter;
|
|
|
|
/** This is the list of different flood counters that we keep for local clients. */
|
|
/* IMPORTANT: If you change this, update floodoption_names[] in src/user.c too !!!!!!!!!!!! */
|
|
typedef enum FloodOption {
|
|
FLD_NICK = 0, /**< nick-flood */
|
|
FLD_JOIN = 1, /**< join-flood */
|
|
FLD_AWAY = 2, /**< away-flood */
|
|
FLD_INVITE = 3, /**< invite-flood */
|
|
FLD_KNOCK = 4, /**< knock-flood */
|
|
FLD_CONVERSATIONS = 5, /**< max-concurrent-conversations */
|
|
FLD_LAG_PENALTY = 6, /**< lag-penalty / lag-penalty-bytes */
|
|
FLD_VHOST = 7, /**< vhost-flood */
|
|
} FloodOption;
|
|
#define MAXFLOODOPTIONS 10
|
|
|
|
typedef struct TrafficStats TrafficStats;
|
|
struct TrafficStats {
|
|
long long messages_sent; /* IRC lines sent */
|
|
long long messages_received; /* IRC lines received */
|
|
long long bytes_sent; /* Bytes sent */
|
|
long long bytes_received; /* Received bytes */
|
|
};
|
|
|
|
/** Socket type (IPv4, IPv6, UNIX) */
|
|
typedef enum {
|
|
SOCKET_TYPE_IPV4=0, SOCKET_TYPE_IPV6=1, SOCKET_TYPE_UNIX=2
|
|
} SocketType;
|
|
|
|
/** This shows the Client struct (any client), the User struct (a user), Server (a server) that are commonly accessed both in the core and by 3rd party coders.
|
|
* @defgroup CommonStructs Common structs
|
|
* @{
|
|
*/
|
|
|
|
/** A client on this or a remote server - can be a user, server, unknown, etc..
|
|
*/
|
|
struct Client {
|
|
struct list_head client_node; /**< For global client list (client_list) */
|
|
struct list_head lclient_node; /**< For local client list (lclient_list) */
|
|
struct list_head special_node; /**< For special lists (server || unknown || oper) */
|
|
LocalClient *local; /**< Additional information regarding locally connected clients */
|
|
User *user; /**< Additional information, if this client is a user */
|
|
Server *server; /**< Additional information, if this is a server */
|
|
RPCClient *rpc; /**< RPC Client, or NULL */
|
|
ClientStatus status; /**< Client status, one of CLIENT_STATUS_* */
|
|
struct list_head client_hash; /**< For name hash table (clientTable) */
|
|
char name[HOSTLEN + 1]; /**< Unique name of the client: nickname for users, hostname for servers */
|
|
time_t lastnick; /**< Timestamp on nick */
|
|
uint64_t flags; /**< Client flags (one or more of CLIENT_FLAG_*) */
|
|
long umodes; /**< Client usermodes (if user) */
|
|
Client *direction; /**< Direction from which this client originated.
|
|
This always points to a directly connected server or &me.
|
|
It is never NULL */
|
|
unsigned char hopcount; /**< Number of servers to this, 0 means local client */
|
|
char ident[USERLEN + 1]; /**< Ident of the user, if available. Otherwise set to "unknown". */
|
|
char info[REALLEN + 1]; /**< Additional client information text. For users this is gecos/realname */
|
|
char id[IDLEN + 1]; /**< Unique ID: SID or UID */
|
|
struct list_head id_hash; /**< For UID/SID hash table (idTable) */
|
|
Client *uplink; /**< Server on where this client is connected to (can be &me) */
|
|
char *ip; /**< IP address of user or server (never NULL) */
|
|
ModData moddata[MODDATA_MAX_CLIENT]; /**< Client attached module data, used by the ModData system */
|
|
};
|
|
|
|
/** Local client information, use client->local to access these (see also @link Client @endlink).
|
|
*/
|
|
struct LocalClient {
|
|
int fd; /**< File descriptor, can be <0 if socket has been closed already. */
|
|
SocketType socket_type; /**< Type of socket: IPv4, IPV6, UNIX */
|
|
SSL *ssl; /**< OpenSSL/LibreSSL struct for TLS connection */
|
|
time_t fake_lag; /**< Time when user will next be allowed to send something (actually fake_lag<currenttime+10) */
|
|
int fake_lag_msec; /**< Used for calculating 'fake_lag' penalty (modulo) */
|
|
time_t creationtime; /**< Time user was created (connected on IRC) */
|
|
time_t last_msg_received; /**< Last time any message was received */
|
|
dbuf sendQ; /**< Outgoing send queue (data to be sent) */
|
|
dbuf recvQ; /**< Incoming receive queue (incoming data yet to be parsed) */
|
|
ConfigItem_class *class; /**< The class { } block associated to this client */
|
|
int proto; /**< PROTOCTL options */
|
|
long caps; /**< User: enabled capabilities (via CAP command) */
|
|
time_t nexttarget; /**< Next time that a new target will be allowed (msg/notice/invite) */
|
|
u_char targets[MAXCCUSERS]; /**< Hash values of targets for target limiting */
|
|
ConfigItem_listen *listener; /**< If this client IsListening() then this is the listener configuration attached to it */
|
|
long serial; /**< Current serial number for send.c functions (to avoid sending duplicate messages) */
|
|
time_t next_nick_allowed; /**< Time the next nick change will be allowed */
|
|
time_t idle_since; /**< Last time a RESETIDLE message was received (PRIVMSG) */
|
|
TrafficStats traffic; /**< Traffic statistics */
|
|
ModData moddata[MODDATA_MAX_LOCAL_CLIENT]; /**< LocalClient attached module data, used by the ModData system */
|
|
char *error_str; /**< Quit reason set by dead_socket() in case of socket/buffer error, later used by exit_client() */
|
|
char sasl_agent[NICKLEN + 1]; /**< SASL: SASL Agent the user is interacting with */
|
|
unsigned char sasl_out; /**< SASL: Number of outgoing sasl messages */
|
|
unsigned char sasl_complete; /**< SASL: >0 if SASL authentication was successful */
|
|
time_t sasl_sent_time; /**< SASL: 0 or the time that the (last) AUTHENTICATE command has been sent */
|
|
char *sni_servername; /**< Servername as sent by client via SNI (Server Name Indication) in TLS, otherwise NULL */
|
|
int cap_protocol; /**< CAP protocol in use. At least 300 for any CAP capable client. 302 for 3.2, etc.. */
|
|
uint32_t nospoof; /**< Anti-spoofing random number (used in user handshake PING/PONG) */
|
|
char *passwd; /**< Password used during connect, if any (freed once connected and set to NULL) */
|
|
int authfd; /**< File descriptor for ident checking (RFC931) */
|
|
int identbufcnt; /**< Counter for 'ident' reading code */
|
|
struct hostent *hostp; /**< Host record for this client (used by DNS code) */
|
|
char sockhost[HOSTLEN + 1]; /**< Hostname from the socket */
|
|
u_short port; /**< Remote TCP port of client */
|
|
FloodCounter flood[MAXFLOODOPTIONS];
|
|
RPCClient *rpc; /**< RPC Client, or NULL */
|
|
};
|
|
|
|
/** User information (persons, not servers), you use client->user to access these (see also @link Client @endlink).
|
|
*/
|
|
struct User {
|
|
Membership *channel; /**< Channels that the user is in (linked list) */
|
|
Link *dccallow; /**< DCCALLOW list (linked list) */
|
|
char account[ACCOUNTLEN + 1]; /**< Services account name or ID (SVID) - use IsLoggedIn(client) to check if logged in */
|
|
int joined; /**< Number of channels joined */
|
|
char username[USERLEN + 1]; /**< Username, the user portion in nick!user@host. */
|
|
char realhost[HOSTLEN + 1]; /**< Realhost, the real host of the user (IP or hostname) - usually this is not shown to other users */
|
|
char cloakedhost[HOSTLEN + 1]; /**< Cloaked host - generated by cloaking algorithm */
|
|
char *virthost; /**< Virtual host - when user has user mode +x this is the active host */
|
|
char *server; /**< Server name the user is on (?) */
|
|
SWhois *swhois; /**< Special "additional" WHOIS entries such as "a Network Administrator" */
|
|
WhoWas *whowas; /**< Something for whowas :D :D */
|
|
char *snomask; /**< Server Notice Mask (snomask) - only for IRCOps */
|
|
char *operlogin; /**< Which oper { } block was used to oper up, otherwise NULL - used for auditting and by oper::maxlogins */
|
|
char *away; /**< AWAY message, or NULL if not away */
|
|
time_t away_since; /**< Last time the user went AWAY */
|
|
};
|
|
|
|
/** Server information (local servers and remote servers), you use client->server to access these (see also @link Client @endlink).
|
|
*/
|
|
struct Server {
|
|
char by[NICKLEN + 1]; /**< Uhhhh - who activated this connection - AGAIN? */
|
|
ConfigItem_link *conf; /**< link { } block associated with this server, or NULL */
|
|
long users; /**< Number of users on this server */
|
|
time_t boottime; /**< Startup time of server (boot time) */
|
|
struct {
|
|
unsigned synced:1; /**< Server synchronization finished? (3.2beta18+) */
|
|
unsigned server_sent:1; /**< SERVER message sent to this link? (for outgoing links) */
|
|
} flags;
|
|
struct {
|
|
char *usermodes; /**< Usermodes that this server knows about */
|
|
char *chanmodes[4]; /**< Channel modes that this server knows (in 4 groups, like CHANMODES= in ISUPPORT/005) */
|
|
int protocol; /**< Link-protocol version */
|
|
char *software; /**< Name of the software (eg: unrealircd-X.Y.Z) */
|
|
char *nickchars; /**< Nick character sets active on this server) */
|
|
} features;
|
|
};
|
|
|
|
/** @} */
|
|
|
|
typedef struct RPCClient RPCClient;
|
|
/** RPC Client information */
|
|
struct RPCClient {
|
|
char *rpc_user; /**< Name of the rpc-user block after authentication, NULL during pre-auth */
|
|
char *issuer; /**< Optional name of the issuer, set by rpc.set_issuer(), eg logged in user on admin panel, can be NULL */
|
|
json_t *rehash_request; /**< If a REHASH (request) is currently running, otherwise NULL */
|
|
LogSource *log_sources; /**< Subscribed to which log sources */
|
|
};
|
|
|
|
struct MessageTag {
|
|
MessageTag *prev, *next;
|
|
char *name;
|
|
char *value;
|
|
};
|
|
|
|
/* conf preprocessor */
|
|
typedef enum PreprocessorItem {
|
|
PREPROCESSOR_ERROR = 0,
|
|
PREPROCESSOR_DEFINE = 1,
|
|
PREPROCESSOR_IF = 2,
|
|
PREPROCESSOR_ENDIF = 3
|
|
} PreprocessorItem;
|
|
|
|
typedef enum PreprocessorPhase {
|
|
PREPROCESSOR_PHASE_INITIAL = 1,
|
|
PREPROCESSOR_PHASE_SECONDARY = 2,
|
|
PREPROCESSOR_PHASE_MODULE = 3
|
|
} PreprocessorPhase;
|
|
|
|
typedef enum AuthenticationType {
|
|
AUTHTYPE_INVALID = -1,
|
|
AUTHTYPE_PLAINTEXT = 0,
|
|
AUTHTYPE_TLS_CLIENTCERT = 1,
|
|
AUTHTYPE_TLS_CLIENTCERTFP = 2,
|
|
AUTHTYPE_SPKIFP = 3,
|
|
AUTHTYPE_UNIXCRYPT = 4,
|
|
AUTHTYPE_BCRYPT = 5,
|
|
AUTHTYPE_ARGON2 = 6,
|
|
} AuthenticationType;
|
|
|
|
typedef struct AuthConfig AuthConfig;
|
|
/** Authentication Configuration - this can be a password or
|
|
* other authentication method that was parsed from the
|
|
* configuration file.
|
|
*/
|
|
struct AuthConfig {
|
|
AuthenticationType type; /**< Type of data, one of AUTHTYPE_* */
|
|
char *data; /**< Data associated with this record */
|
|
};
|
|
|
|
#ifndef HAVE_CRYPT
|
|
#define crypt DES_crypt
|
|
#endif
|
|
|
|
/* CRULE stuff */
|
|
|
|
#define CRULE_ALL 0
|
|
#define CRULE_AUTO 1
|
|
|
|
/* some constants and shared data types */
|
|
#define CR_MAXARGLEN 80 /**< Maximum arg length (must be > HOSTLEN) */
|
|
#define CR_MAXARGS 3 /**< Maximum number of args for a rule */
|
|
|
|
/** Evaluation function for a connection rule. */
|
|
typedef int (*crule_funcptr) (int, void **);
|
|
|
|
/** CRULE - Node in a connection rule tree. */
|
|
struct CRuleNode {
|
|
crule_funcptr funcptr; /**< Evaluation function for this node. */
|
|
int numargs; /**< Number of arguments. */
|
|
void *arg[CR_MAXARGS]; /**< Array of arguments. For operators, each arg
|
|
is a tree element; for functions, each arg is
|
|
a string. */
|
|
};
|
|
typedef struct CRuleNode CRuleNode;
|
|
typedef struct CRuleNode* CRuleNodePtr;
|
|
|
|
|
|
/*
|
|
* conf2 stuff -stskeeps
|
|
*/
|
|
|
|
typedef enum ConfigIfCondition { IF_DEFINED=1, IF_VALUE=2, IF_MODULE=3} ConfigIfCondition;
|
|
|
|
struct ConditionalConfig
|
|
{
|
|
ConditionalConfig *prev, *next;
|
|
int priority; /**< Preprocessor level. Starts with 1, then 2, 3, .. */
|
|
ConfigIfCondition condition; /**< See ConfigIfCondition, one of: IF_* */
|
|
int negative; /**< For ! conditions */
|
|
char *name; /**< Name of the variable or module */
|
|
char *opt; /**< Only for IF_VALUE */
|
|
};
|
|
|
|
/** Configuration file (config parser) */
|
|
struct ConfigFile
|
|
{
|
|
char *filename; /**< Filename of configuration file */
|
|
ConfigEntry *items; /**< All items in the configuration file */
|
|
ConfigFile *next; /**< Next configuration file */
|
|
};
|
|
|
|
/** Configuration entry (config parser) */
|
|
struct ConfigEntry
|
|
{
|
|
char *name; /**< Variable name */
|
|
char *value; /**< Variable value, can be NULL */
|
|
ConfigEntry *next; /**< Next ConfigEntry */
|
|
ConfigEntry *items; /**< Items (children), can be NULL */
|
|
ConfigFile *file; /**< To which configfile does this belong? */
|
|
int line_number; /**< Line number of the variable name (this one is usually used for errors) */
|
|
int file_position_start; /**< Position (byte) within configuration file of the start of the block, rarely used */
|
|
int file_position_end; /**< Position (byte) within configuration file of the end of the block, rarely used */
|
|
int section_linenumber; /**< Line number of the section (only used internally for parse errors) */
|
|
ConfigEntry *parent; /**< Parent item, can be NULL */
|
|
ConditionalConfig *conditional_config; /**< Used for conditional config by the main parser */
|
|
unsigned escaped:1;
|
|
};
|
|
|
|
struct ConfigFlag
|
|
{
|
|
unsigned temporary : 1;
|
|
unsigned permanent : 1;
|
|
};
|
|
|
|
/* configflag specialized for except socks/ban -Stskeeps */
|
|
|
|
struct ConfigFlag_except
|
|
{
|
|
unsigned temporary : 1;
|
|
unsigned type : 4;
|
|
};
|
|
|
|
struct ConfigFlag_ban
|
|
{
|
|
unsigned temporary : 1;
|
|
unsigned type : 4;
|
|
unsigned type2 : 2;
|
|
};
|
|
|
|
struct ConfigFlag_tld
|
|
{
|
|
unsigned temporary : 1;
|
|
unsigned motdptr : 1;
|
|
unsigned ruleclient : 1;
|
|
};
|
|
|
|
#define CONF_BAN_SERVER 1
|
|
#define CONF_BAN_VERSION 2
|
|
#define CONF_BAN_REALNAME 3
|
|
|
|
#define CONF_BAN_TYPE_CONF 0
|
|
#define CONF_BAN_TYPE_AKILL 1
|
|
#define CONF_BAN_TYPE_TEMPORARY 2
|
|
|
|
struct ConfigItem {
|
|
ConfigItem *prev, *next;
|
|
ConfigFlag flag;
|
|
};
|
|
|
|
struct ConfigItem_me {
|
|
char *name, *info, *sid;
|
|
};
|
|
|
|
struct ConfigItem_files {
|
|
char *motd_file, *rules_file, *smotd_file;
|
|
char *botmotd_file, *opermotd_file, *svsmotd_file;
|
|
char *pid_file, *tune_file;
|
|
};
|
|
|
|
struct ConfigItem_admin {
|
|
ConfigItem_admin *prev, *next;
|
|
ConfigFlag flag;
|
|
char *line;
|
|
};
|
|
|
|
#define CLASS_OPT_NOFAKELAG 0x1
|
|
|
|
struct ConfigItem_class {
|
|
ConfigItem_class *prev, *next;
|
|
ConfigFlag flag;
|
|
char *name;
|
|
int pingfreq, connfreq, maxclients, sendq, recvq, clients;
|
|
int xrefcount; /* EXTRA reference count, 'clients' also acts as a reference count but
|
|
* link blocks also refer to classes so a 2nd ref. count was needed.
|
|
*/
|
|
unsigned int options;
|
|
};
|
|
|
|
struct ConfigFlag_allow {
|
|
unsigned noident :1;
|
|
unsigned useip :1;
|
|
unsigned tls :1;
|
|
unsigned reject_on_auth_failure :1;
|
|
};
|
|
|
|
/** allow { } block settings */
|
|
struct ConfigItem_allow {
|
|
ConfigItem_allow *prev, *next;
|
|
ConfigFlag flag;
|
|
SecurityGroup *match;
|
|
char *server;
|
|
AuthConfig *auth;
|
|
int maxperip; /**< Maximum connections permitted per IP address (locally) */
|
|
int global_maxperip; /**< Maximum connections permitted per IP address (globally) */
|
|
int port;
|
|
ConfigItem_class *class;
|
|
ConfigFlag_allow flags;
|
|
int ipv6_clone_mask;
|
|
};
|
|
|
|
struct OperClassACLPath
|
|
{
|
|
OperClassACLPath *prev,*next;
|
|
char *identifier;
|
|
};
|
|
|
|
struct OperClassACLEntryVar
|
|
{
|
|
OperClassACLEntryVar *prev,*next;
|
|
char *name;
|
|
char *value;
|
|
};
|
|
|
|
struct OperClassACLEntry
|
|
{
|
|
OperClassACLEntry *prev,*next;
|
|
OperClassACLEntryVar *variables;
|
|
OperClassEntryType type;
|
|
};
|
|
|
|
struct OperClassACL
|
|
{
|
|
OperClassACL *prev,*next;
|
|
char *name;
|
|
OperClassACLEntry *entries;
|
|
OperClassACL *acls;
|
|
};
|
|
|
|
struct OperClass
|
|
{
|
|
char *ISA;
|
|
char *name;
|
|
OperClassACL *acls;
|
|
};
|
|
|
|
struct OperClassCheckParams
|
|
{
|
|
Client *client;
|
|
Client *victim;
|
|
Channel *channel;
|
|
const void *extra;
|
|
};
|
|
|
|
struct ConfigItem_operclass {
|
|
ConfigItem_operclass *prev, *next;
|
|
OperClass *classStruct;
|
|
};
|
|
|
|
struct ConfigItem_oper {
|
|
ConfigItem_oper *prev, *next;
|
|
ConfigFlag flag;
|
|
char *name, *snomask;
|
|
SWhois *swhois;
|
|
AuthConfig *auth;
|
|
char *operclass;
|
|
ConfigItem_class *class;
|
|
SecurityGroup *match;
|
|
unsigned long modes, require_modes;
|
|
char *vhost;
|
|
int maxlogins;
|
|
int server_notice_colors;
|
|
int server_notice_show_event;
|
|
int auto_login;
|
|
};
|
|
|
|
/** The TLS options that are used in set::tls and otherblocks::tls-options.
|
|
* NOTE: If you add something here then you must also update the
|
|
* conf_tlsblock() function in s_conf.c to have it inherited
|
|
* from set::tls to the other config blocks!
|
|
*/
|
|
typedef struct TLSOptions TLSOptions;
|
|
struct TLSOptions {
|
|
char *certificate_file;
|
|
char *key_file;
|
|
char *trusted_ca_file;
|
|
unsigned int protocols;
|
|
char *ciphers;
|
|
char *ciphersuites;
|
|
char *ecdh_curves;
|
|
char *outdated_protocols;
|
|
char *outdated_ciphers;
|
|
long options;
|
|
int renegotiate_bytes;
|
|
int renegotiate_timeout;
|
|
int sts_port;
|
|
long sts_duration;
|
|
int sts_preload;
|
|
};
|
|
|
|
struct ConfigItem_mask {
|
|
ConfigItem_mask *prev, *next;
|
|
ConfigFlag flag;
|
|
char *mask;
|
|
};
|
|
|
|
struct ConfigItem_drpass {
|
|
AuthConfig *restartauth;
|
|
AuthConfig *dieauth;
|
|
};
|
|
|
|
struct ConfigItem_ulines {
|
|
ConfigItem_ulines *prev, *next;
|
|
ConfigFlag flag;
|
|
char *servername;
|
|
};
|
|
|
|
#define TLD_TLS 0x1
|
|
#define TLD_REMOTE 0x2
|
|
|
|
struct ConfigItem_tld {
|
|
ConfigItem_tld *prev, *next;
|
|
ConfigFlag_tld flag;
|
|
SecurityGroup *match;
|
|
char *channel;
|
|
char *motd_file, *rules_file, *smotd_file;
|
|
char *botmotd_file, *opermotd_file;
|
|
MOTDFile rules, motd, smotd, botmotd, opermotd;
|
|
u_short options;
|
|
};
|
|
|
|
#define WEB_OPT_ENABLE 0x1
|
|
|
|
typedef enum HttpMethod {
|
|
HTTP_METHOD_NONE = 0, /**< No valid HTTP request (yet) */
|
|
HTTP_METHOD_HEAD = 1, /**< HEAD request */
|
|
HTTP_METHOD_GET = 2, /**< GET request */
|
|
HTTP_METHOD_PUT = 3, /**< PUT request */
|
|
HTTP_METHOD_POST = 4, /**< POST request */
|
|
} HttpMethod;
|
|
|
|
typedef enum TransferEncoding {
|
|
TRANSFER_ENCODING_NONE=0,
|
|
TRANSFER_ENCODING_CHUNKED=1
|
|
} TransferEncoding;
|
|
|
|
typedef struct WebRequest WebRequest;
|
|
struct WebRequest {
|
|
HttpMethod method; /**< GET/PUT/POST */
|
|
char *uri; /**< Requested resource, eg "/api" */
|
|
NameValuePrioList *headers; /**< HTTP request headers */
|
|
int num_headers; /**< Number of HTTP request headers (also used for sorting the list) */
|
|
char request_header_parsed; /**< Done parsing? */
|
|
char *lefttoparse; /**< Leftover buffer to parse */
|
|
int lefttoparselen; /**< Length of lefttoparse buffer */
|
|
int pending_close; /**< Set to 1 when connection should be closed as soon as all data is sent (sendq==0) */
|
|
char *request_buffer; /**< Buffer for POST data */
|
|
int request_buffer_size; /**< Size of buffer for POST data */
|
|
int request_body_complete; /**< POST data has all been read */
|
|
long long content_length; /**< "Content-Length" as sent by the client */
|
|
long long chunk_remaining;
|
|
TransferEncoding transfer_encoding;
|
|
long long config_max_request_buffer_size; /**< CONFIG: Maximum request length allowed */
|
|
};
|
|
|
|
typedef struct WebServer WebServer;
|
|
struct WebServer {
|
|
int (*handle_request)(Client *client, WebRequest *web);
|
|
int (*handle_body)(Client *client, WebRequest *web, const char *buf, int length);
|
|
};
|
|
|
|
typedef enum WebSocketType {
|
|
WEBSOCKET_TYPE_BINARY = 1,
|
|
WEBSOCKET_TYPE_TEXT = 2
|
|
} WebSocketType;
|
|
|
|
typedef struct WebSocketUser WebSocketUser;
|
|
struct WebSocketUser {
|
|
char get; /**< GET initiated */
|
|
char handshake_completed; /**< Handshake completed, use websocket frames */
|
|
char *handshake_key; /**< Handshake key (used during handshake) */
|
|
char *lefttoparse; /**< Leftover buffer to parse */
|
|
int lefttoparselen; /**< Length of lefttoparse buffer */
|
|
WebSocketType type; /**< WEBSOCKET_TYPE_BINARY or WEBSOCKET_TYPE_TEXT */
|
|
char *sec_websocket_protocol; /**< Only valid during parsing of the request, after that it is NULL again */
|
|
char *forwarded; /**< Unparsed `Forwarded:` header, RFC 7239 */
|
|
int secure; /**< If there is a Forwarded header, this indicates if the remote connection is secure */
|
|
};
|
|
|
|
#define WEBSOCKET_MAGIC_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" /* see RFC6455 */
|
|
|
|
/* Websocket operations: */
|
|
#define WSOP_CONTINUATION 0x00
|
|
#define WSOP_TEXT 0x01
|
|
#define WSOP_BINARY 0x02
|
|
#define WSOP_CLOSE 0x08
|
|
#define WSOP_PING 0x09
|
|
#define WSOP_PONG 0x0a
|
|
|
|
struct ConfigItem_listen {
|
|
ConfigItem_listen *prev, *next;
|
|
ConfigFlag flag;
|
|
SocketType socket_type; /**< Socket type, eg. SOCKET_TYPE_IPV4 or SOCKET_TYPE_UNIX */
|
|
char *file; /**< If the listener is a file, the full pathname */
|
|
char *ip; /**< IP bind address (if IP listener) */
|
|
int port; /**< Port to listen on (if IP listener) */
|
|
int mode; /**< Mode permissions (if file aka unix socket listener) */
|
|
int options; /**< e.g. LISTENER_BOUND if active */
|
|
int clients; /**< Clients connected to this socket / listener */
|
|
int fd; /**< File descriptor (if open), or -1 (if not open yet) */
|
|
char *spoof_ip; /**< listen::spoof-ip (only for listen::file, if you want to override 127.0.0.1) */
|
|
SSL_CTX *ssl_ctx; /**< SSL/TLS context */
|
|
TLSOptions *tls_options; /**< SSL/TLS options */
|
|
WebServer *webserver; /**< For the webserver module */
|
|
void (*start_handshake)(Client *client); /**< Function to call on accept() */
|
|
int websocket_options; /**< Websocket options (for the websocket module) */
|
|
int rpc_options; /**< For the RPC module */
|
|
char *websocket_forward; /**< For websocket module too */
|
|
};
|
|
|
|
struct ConfigItem_sni {
|
|
ConfigItem_sni *prev, *next;
|
|
ConfigFlag flag;
|
|
char *name;
|
|
SSL_CTX *ssl_ctx;
|
|
TLSOptions *tls_options;
|
|
};
|
|
|
|
struct ConfigItem_vhost {
|
|
ConfigItem_vhost *prev, *next;
|
|
ConfigFlag flag;
|
|
SecurityGroup *match;
|
|
char *login, *virthost, *virtuser;
|
|
SWhois *swhois;
|
|
AuthConfig *auth;
|
|
};
|
|
|
|
struct ConfigItem_link {
|
|
ConfigItem_link *prev, *next;
|
|
ConfigFlag flag;
|
|
/* config options: */
|
|
char *servername; /**< Name of the server ('link <servername> { }') */
|
|
struct {
|
|
SecurityGroup *match; /**< incoming mask(s) to accept */
|
|
} incoming;
|
|
struct {
|
|
char *file; /**< UNIX domain socket to connect to */
|
|
char *bind_ip; /**< Our IP to bind to when doing the connect */
|
|
char *hostname; /**< Hostname or IP to connect to */
|
|
int port; /**< Port to connect to */
|
|
int options; /**< Connect options like tls or autoconnect */
|
|
} outgoing;
|
|
AuthConfig *auth; /**< authentication method (eg: password) */
|
|
char *hub; /**< Hub mask */
|
|
char *leaf; /**< Leaf mask */
|
|
int leaf_depth; /**< Leaf depth */
|
|
ConfigItem_class *class; /**< Class the server should use */
|
|
int options; /**< Generic options such as quarantine */
|
|
int verify_certificate;
|
|
/* internal: */
|
|
int refcount; /**< Reference counter (used so we know if the struct may be freed) */
|
|
time_t hold; /**< For how long the server is "on hold" for outgoing connects (why?) */
|
|
char *connect_ip; /**< actual IP to use for outgoing connect (filled in after host is resolved) */
|
|
SSL_CTX *ssl_ctx; /**< SSL Context for outgoing connection (optional) */
|
|
TLSOptions *tls_options; /**< SSL Options for outgoing connection (optional) */
|
|
};
|
|
|
|
struct ConfigItem_ban {
|
|
ConfigItem_ban *prev, *next;
|
|
ConfigFlag_ban flag;
|
|
char *mask, *reason;
|
|
unsigned short action;
|
|
};
|
|
|
|
struct ConfigItem_deny_dcc {
|
|
ConfigItem_deny_dcc *prev, *next;
|
|
ConfigFlag_ban flag;
|
|
char *filename, *reason;
|
|
};
|
|
|
|
struct ConfigItem_deny_version {
|
|
ConfigItem_deny_version *prev, *next;
|
|
ConfigFlag flag;
|
|
char *mask, *version, *flags;
|
|
};
|
|
|
|
struct ConfigItem_deny_channel {
|
|
ConfigItem_deny_channel *prev, *next;
|
|
ConfigFlag flag;
|
|
char *channel, *reason, *redirect, *class;
|
|
unsigned char warn;
|
|
SecurityGroup *match;
|
|
};
|
|
|
|
struct ConfigItem_allow_channel {
|
|
ConfigItem_allow_channel *prev, *next;
|
|
ConfigFlag flag;
|
|
char *channel, *class;
|
|
SecurityGroup *match;
|
|
};
|
|
|
|
struct ConfigItem_allow_dcc {
|
|
ConfigItem_allow_dcc *prev, *next;
|
|
ConfigFlag_ban flag;
|
|
char *filename;
|
|
};
|
|
|
|
typedef enum {
|
|
ALIAS_SERVICES=1, ALIAS_STATS, ALIAS_NORMAL, ALIAS_COMMAND, ALIAS_CHANNEL, ALIAS_REAL
|
|
} AliasType;
|
|
|
|
struct ConfigItem_alias {
|
|
ConfigItem_alias *prev, *next;
|
|
ConfigFlag flag;
|
|
ConfigItem_alias_format *format;
|
|
char *alias, *nick;
|
|
AliasType type;
|
|
unsigned int spamfilter:1;
|
|
};
|
|
|
|
struct ConfigItem_alias_format {
|
|
ConfigItem_alias_format *prev, *next;
|
|
ConfigFlag flag;
|
|
char *nick;
|
|
AliasType type;
|
|
char *format, *parameters;
|
|
Match *expr;
|
|
};
|
|
|
|
#define RESOURCE_REMOTE 0x1
|
|
#define RESOURCE_DLQUEUED 0x2
|
|
#define RESOURCE_INCLUDE 0x4
|
|
|
|
typedef struct ConfigEntryWrapper ConfigEntryWrapper;
|
|
struct ConfigEntryWrapper {
|
|
ConfigEntryWrapper *prev, *next;
|
|
ConfigEntry *ce;
|
|
};
|
|
|
|
struct ConfigResource {
|
|
ConfigResource *prev, *next;
|
|
int type;
|
|
ConfigEntryWrapper *wce; /**< The place(s) where this resource is begin used */
|
|
char *file; /**< File to read: can be a conf/something file or a downloaded file */
|
|
char *url; /**< URL, if it is an URL */
|
|
char *cache_file; /**< Set to filename of local cached copy, if it is available */
|
|
};
|
|
|
|
struct ConfigItem_blacklist_module {
|
|
ConfigItem_blacklist_module *prev, *next;
|
|
char *name;
|
|
};
|
|
|
|
struct ConfigItem_help {
|
|
ConfigItem_help *prev, *next;
|
|
ConfigFlag flag;
|
|
char *command;
|
|
MOTDLine *text;
|
|
};
|
|
|
|
struct ConfigItem_offchans {
|
|
ConfigItem_offchans *prev, *next;
|
|
char name[CHANNELLEN+1];
|
|
char *topic;
|
|
};
|
|
|
|
#define SECURITYGROUPLEN 48
|
|
struct SecurityGroup {
|
|
SecurityGroup *prev, *next;
|
|
int priority;
|
|
char name[SECURITYGROUPLEN+1];
|
|
NameValuePrioList *printable_list;
|
|
int printable_list_counter;
|
|
/* Include */
|
|
int identified;
|
|
int reputation_score;
|
|
long connect_time;
|
|
int webirc;
|
|
int websocket;
|
|
int tls;
|
|
NameList *ip;
|
|
ConfigItem_mask *mask;
|
|
NameList *security_group;
|
|
NameValuePrioList *extended;
|
|
/* Exclude */
|
|
int exclude_identified;
|
|
int exclude_reputation_score;
|
|
long exclude_connect_time;
|
|
int exclude_webirc;
|
|
int exclude_websocket;
|
|
int exclude_tls;
|
|
NameList *exclude_ip;
|
|
ConfigItem_mask *exclude_mask;
|
|
NameList *exclude_security_group;
|
|
NameValuePrioList *exclude_extended;
|
|
};
|
|
|
|
#define HM_HOST 1
|
|
#define HM_IPV4 2
|
|
#define HM_IPV6 3
|
|
|
|
#define SETTER_NICK 0
|
|
#define SETTER_NICK_USER_HOST 1
|
|
|
|
/*
|
|
* statistics structures
|
|
*/
|
|
typedef struct IRCStatistics IRCStatistics;
|
|
struct IRCStatistics {
|
|
unsigned int is_cl; /* number of client connections */
|
|
unsigned int is_sv; /* number of server connections */
|
|
unsigned int is_ni; /* connection but no idea who it was */
|
|
time_t is_cti; /* time spent connected by clients */
|
|
time_t is_sti; /* time spent connected by servers */
|
|
unsigned int is_ac; /* connections accepted */
|
|
unsigned int is_ref; /* accepts refused */
|
|
unsigned int is_unco; /* unknown commands */
|
|
unsigned int is_wrdi; /* command going in wrong direction */
|
|
unsigned int is_unpf; /* unknown prefix */
|
|
unsigned int is_empt; /* empty message */
|
|
unsigned int is_num; /* numeric message */
|
|
unsigned int is_kill; /* number of kills generated on collisions */
|
|
unsigned int is_fake; /* MODE 'fakes' */
|
|
unsigned int is_asuc; /* successful auth requests */
|
|
unsigned int is_abad; /* bad auth requests */
|
|
unsigned int is_udp; /* packets recv'd on udp port */
|
|
unsigned int is_loc; /* local connections made */
|
|
};
|
|
|
|
#define EXTCMODETABLESZ 32
|
|
|
|
/* Number of maximum paramter modes to allow.
|
|
* Don't set it unnecessarily high.. we only use k, l, L, j and f at the moment.
|
|
*/
|
|
#define MAXPARAMMODES 16
|
|
|
|
/** Channel Mode.
|
|
* NOTE: you normally don't access these struct members directly.
|
|
* For simple checking if a mode is set, use has_channel_mode()
|
|
* Otherwise, see the extended channel modes API, CmodeAdd(), etc.
|
|
*/
|
|
struct Mode {
|
|
Cmode_t mode; /**< Other ("extended") channel modes set on this channel */
|
|
void *mode_params[MAXPARAMMODES+1]; /**< Parameters for extended channel modes */
|
|
};
|
|
|
|
/* flags for Link if used to contain Watch --k4be */
|
|
|
|
/* WATCH type */
|
|
#define WATCH_FLAG_TYPE_WATCH (1<<0) /* added via /WATCH command */
|
|
#define WATCH_FLAG_TYPE_MONITOR (1<<1) /* added via /MONITOR command */
|
|
|
|
/* behaviour switches */
|
|
#define WATCH_FLAG_AWAYNOTIFY (1<<8) /* should send AWAY notifications */
|
|
|
|
/* watch triggering events */
|
|
#define WATCH_EVENT_ONLINE 0
|
|
#define WATCH_EVENT_OFFLINE 1
|
|
#define WATCH_EVENT_AWAY 2
|
|
#define WATCH_EVENT_NOTAWAY 3
|
|
#define WATCH_EVENT_REAWAY 4
|
|
#define WATCH_EVENT_USERHOST 5
|
|
#define WATCH_EVENT_REALNAME 6
|
|
#define WATCH_EVENT_LOGGEDIN 7
|
|
#define WATCH_EVENT_LOGGEDOUT 8
|
|
|
|
/* Used for notify-hash buckets... -Donwulff */
|
|
|
|
struct Watch {
|
|
Watch *hnext;
|
|
time_t lasttime;
|
|
Link *watch;
|
|
char nick[1];
|
|
};
|
|
|
|
/** General link structure used for certain chains (watch list, invite list, dccallow).
|
|
* Note that these always require you to use the make_link() and free_link() functions.
|
|
* Do not combine with other alloc/free functions!!
|
|
*/
|
|
struct Link {
|
|
struct Link *next;
|
|
int flags;
|
|
union {
|
|
Client *client;
|
|
Channel *channel;
|
|
Watch *wptr;
|
|
/* there used to be 'char *cp' here too,
|
|
* but in such a case you better use NameList
|
|
* instead of Link!
|
|
*/
|
|
} value;
|
|
};
|
|
|
|
#define IsInvalidChannelTS(x) ((x) <= 1000000) /**< Invalid channel creation time */
|
|
|
|
/**
|
|
* @addtogroup CommonStructs
|
|
* @{
|
|
*/
|
|
|
|
/** A channel on IRC */
|
|
struct Channel {
|
|
struct Channel *nextch; /**< Next channel in linked list (channel) */
|
|
struct Channel *prevch; /**< Previous channel in linked list (channel) */
|
|
struct Channel *hnextch; /**< Next channel in hash table */
|
|
Mode mode; /**< Channel Mode set on this channel */
|
|
time_t creationtime; /**< When the channel was first created */
|
|
char *topic; /**< Channel TOPIC */
|
|
char *topic_nick; /**< Person (or server) who set the TOPIC */
|
|
time_t topic_time; /**< Time at which the topic was last set */
|
|
int users; /**< Number of users in the channel */
|
|
Member *members; /**< List of channel members (users in the channel) */
|
|
Ban *banlist; /**< List of bans (+b) */
|
|
Ban *exlist; /**< List of ban exceptions (+e) */
|
|
Ban *invexlist; /**< List of invite exceptions (+I) */
|
|
char *mode_lock; /**< Mode lock (MLOCK) applied to channel - usually by Services */
|
|
ModData moddata[MODDATA_MAX_CHANNEL]; /**< Channel attached module data, used by the ModData system */
|
|
char name[CHANNELLEN+1]; /**< Channel name */
|
|
};
|
|
|
|
/** user/channel member struct (channel->members).
|
|
* This is Member which is used in the linked list channel->members for each channel.
|
|
* There is also Membership which is used in client->user->channels (see Membership for that).
|
|
* Both must be kept synchronized 100% at all times.
|
|
*/
|
|
struct Member
|
|
{
|
|
struct Member *next; /**< Next entry in list */
|
|
Client *client; /**< The client */
|
|
char member_modes[MEMBERMODESLEN]; /**< The access of the user on this channel (eg "vhoqa") */
|
|
ModData moddata[MODDATA_MAX_MEMBER]; /** Member attached module data, used by the ModData system */
|
|
};
|
|
|
|
/** user/channel membership struct (client->user->channels).
|
|
* This is Membership which is used in the linked list client->user->channels for each user.
|
|
* There is also Member which is used in channel->members (see Member for that).
|
|
* Both must be kept synchronized 100% at all times.
|
|
*/
|
|
struct Membership
|
|
{
|
|
struct Membership *next; /**< Next entry in list */
|
|
struct Channel *channel; /**< The channel */
|
|
char member_modes[MEMBERMODESLEN]; /**< The (new) access of the user on this channel (eg "vhoqa") */
|
|
ModData moddata[MODDATA_MAX_MEMBERSHIP]; /**< Membership attached module data, used by the ModData system */
|
|
};
|
|
|
|
/** @} */
|
|
|
|
/** A ban, exempt or invite exception entry */
|
|
struct Ban {
|
|
struct Ban *next; /**< Next entry in list */
|
|
char *banstr; /**< The string (eg: *!*@*.example.org) */
|
|
char *who; /**< Person or server who set the entry (eg: Nick) */
|
|
time_t when; /**< When the entry was added */
|
|
};
|
|
|
|
/* Channel macros */
|
|
#define MODE_EXCEPT 0x0200
|
|
#define MODE_BAN 0x0400
|
|
#define MODE_INVEX 0x8000000
|
|
|
|
/* name invisible */
|
|
#define SecretChannel(x) ((x) && has_channel_mode((x), 's'))
|
|
/* channel not shown but names are */
|
|
#define HiddenChannel(x) ((x) && has_channel_mode((x), 'p'))
|
|
/* channel visible */
|
|
#define ShowChannel(v,c) (PubChannel(c) || IsMember((v),(c)))
|
|
#define PubChannel(x) (!SecretChannel((x)) && !HiddenChannel((x)))
|
|
|
|
#define IsChannelName(name) ((name) && (*(name) == '#'))
|
|
|
|
#define IsMember(blah,chan) ((blah && blah->user && \
|
|
find_membership_link((blah->user)->channel, chan)) ? 1 : 0)
|
|
|
|
|
|
/* Misc macros */
|
|
|
|
#define BadPtr(x) (!(x) || (*(x) == '\0'))
|
|
|
|
/** Is valid character in nick? [not for external usage, use do_check_nickname instead!] */
|
|
#define isvalid(c) (char_atribs[(u_char)(c)]&ALLOWN)
|
|
|
|
|
|
#define TStime() (timeofday)
|
|
|
|
/* used in SetMode() in channel.c and cmd_umode() in s_msg.c */
|
|
|
|
#define MODE_NULL 0
|
|
#define MODE_ADD 0x40000000
|
|
#define MODE_DEL 0x20000000
|
|
|
|
/* return values for hunt_server() */
|
|
|
|
#define HUNTED_NOSUCH (-1) /* if the hunted server is not found */
|
|
#define HUNTED_ISME 0 /* if this server should execute the command */
|
|
#define HUNTED_PASS 1 /* if message passed onwards successfully */
|
|
|
|
/* used when sending to #mask or $mask */
|
|
|
|
#define MATCH_SERVER 1
|
|
#define MATCH_HOST 2
|
|
|
|
/* misc variable externs */
|
|
|
|
extern MODVAR char *version, *infotext[], *dalinfotext[], *unrealcredits[], *unrealinfo[];
|
|
extern MODVAR char *generation, *creation;
|
|
extern MODVAR char *gnulicense[];
|
|
/* misc defines */
|
|
|
|
#define COMMA ","
|
|
|
|
#define isexcept void
|
|
|
|
extern MODVAR SSL_CTX *ctx;
|
|
extern MODVAR SSL_CTX *ctx_server;
|
|
extern MODVAR SSL_CTX *ctx_client;
|
|
|
|
#define TLS_PROTOCOL_TLSV1 0x0001
|
|
#define TLS_PROTOCOL_TLSV1_1 0x0002
|
|
#define TLS_PROTOCOL_TLSV1_2 0x0004
|
|
#define TLS_PROTOCOL_TLSV1_3 0x0008
|
|
|
|
#define TLS_PROTOCOL_ALL 0xffff
|
|
|
|
struct ThrottlingBucket
|
|
{
|
|
struct ThrottlingBucket *prev, *next;
|
|
char *ip;
|
|
time_t since;
|
|
char count;
|
|
};
|
|
|
|
typedef struct CoreChannelModeTable CoreChannelModeTable;
|
|
struct CoreChannelModeTable {
|
|
long mode; /**< Mode value (which bit will be set) */
|
|
char flag; /**< Mode letter (eg: 't') */
|
|
unsigned halfop : 1; /**< May halfop set this mode? 1/0 */
|
|
unsigned parameters : 1; /**< Mode requires a parameter? 1/0 */
|
|
};
|
|
|
|
/** Parse channel mode */
|
|
typedef struct ParseMode ParseMode;
|
|
struct ParseMode {
|
|
int what;
|
|
char modechar;
|
|
char *param;
|
|
Cmode *extm;
|
|
const char *modebuf; /* curr pos */
|
|
const char *parabuf; /* curr pos */
|
|
char buf[512]; /* internal parse buffer */
|
|
};
|
|
|
|
#define MAXMULTILINEMODES 3
|
|
typedef struct MultiLineMode MultiLineMode;
|
|
struct MultiLineMode {
|
|
char *modeline[MAXMULTILINEMODES+1];
|
|
char *paramline[MAXMULTILINEMODES+1];
|
|
int numlines;
|
|
};
|
|
|
|
typedef struct PendingServer PendingServer;
|
|
struct PendingServer {
|
|
PendingServer *prev, *next;
|
|
char sid[IDLEN+1];
|
|
};
|
|
|
|
typedef struct PendingNet PendingNet;
|
|
struct PendingNet {
|
|
PendingNet *prev, *next; /* Previous and next in list */
|
|
Client *client; /**< Client to which these servers belong */
|
|
PendingServer *servers; /**< The list of servers connected to the client */
|
|
};
|
|
|
|
extern void init_throttling();
|
|
extern struct ThrottlingBucket *find_throttling_bucket(Client *);
|
|
extern void add_throttling_bucket(Client *);
|
|
extern int throttle_can_connect(Client *);
|
|
|
|
typedef struct MaxTarget MaxTarget;
|
|
struct MaxTarget {
|
|
MaxTarget *prev, *next;
|
|
char *cmd;
|
|
int limit;
|
|
};
|
|
#define MAXTARGETS_MAX 1000000 /* used for 'max' */
|
|
|
|
#define VERIFY_OPERCOUNT(clnt,tag) { if (irccounts.operators < 0) verify_opercount(clnt,tag); } while(0)
|
|
|
|
#define MARK_AS_OFFICIAL_MODULE(modinf) do { if (modinf && modinf->handle) ModuleSetOptions(modinfo->handle, MOD_OPT_OFFICIAL, 1); } while(0)
|
|
#define MARK_AS_GLOBAL_MODULE(modinf) do { if (modinf && modinf->handle) ModuleSetOptions(modinfo->handle, MOD_OPT_GLOBAL, 1); } while(0)
|
|
|
|
/* used for is_banned type field: */
|
|
#define BANCHK_JOIN 0x0001 /* checking if a ban forbids the person from joining */
|
|
#define BANCHK_MSG 0x0002 /* checking if a ban forbids the person from sending messages */
|
|
#define BANCHK_NICK 0x0004 /* checking if a ban forbids the person from changing his/her nick */
|
|
#define BANCHK_LEAVE_MSG 0x0008 /* checking if a ban forbids the person from leaving a message in PART or QUIT */
|
|
#define BANCHK_TKL 0x0010 /* called from a server ban routine, or other match_user() usage */
|
|
#define BANCHK_ALL (BANCHK_JOIN|BANCHK_MSG|BANCHK_NICK|BANCHK_LEAVE_MSG) /* all events except BANCHK_TKL which is special */
|
|
|
|
#define TKLISTLEN 26
|
|
#define TKLIPHASHLEN1 4
|
|
#define TKLIPHASHLEN2 1021
|
|
|
|
#define MATCH_CHECK_IP 0x0001
|
|
#define MATCH_CHECK_REAL_HOST 0x0002
|
|
#define MATCH_CHECK_CLOAKED_HOST 0x0004
|
|
#define MATCH_CHECK_VISIBLE_HOST 0x0008
|
|
#define MATCH_CHECK_EXTENDED 0x0010
|
|
|
|
#define MATCH_CHECK_ALL (MATCH_CHECK_IP|MATCH_CHECK_REAL_HOST|MATCH_CHECK_CLOAKED_HOST|MATCH_CHECK_VISIBLE_HOST|MATCH_CHECK_EXTENDED)
|
|
#define MATCH_CHECK_REAL (MATCH_CHECK_IP|MATCH_CHECK_REAL_HOST|MATCH_CHECK_EXTENDED)
|
|
|
|
#define MATCH_MASK_IS_UHOST 0x1000
|
|
#define MATCH_MASK_IS_HOST 0x2000
|
|
|
|
typedef enum {
|
|
POLICY_ALLOW=1,
|
|
POLICY_WARN=2,
|
|
POLICY_DENY=3
|
|
} Policy;
|
|
|
|
#define NO_EXIT_CLIENT 99
|
|
|
|
/*-- badwords --*/
|
|
|
|
#define MAX_MATCH 1
|
|
#define MAX_WORDLEN 64
|
|
|
|
#define PATTERN "\\w*%s\\w*"
|
|
#define REPLACEWORD "<censored>"
|
|
|
|
#define BADW_TYPE_INVALID 0x0
|
|
#define BADW_TYPE_FAST 0x1
|
|
#define BADW_TYPE_FAST_L 0x2
|
|
#define BADW_TYPE_FAST_R 0x4
|
|
#define BADW_TYPE_REGEX 0x8
|
|
|
|
#define BADWORD_REPLACE 1
|
|
#define BADWORD_BLOCK 2
|
|
|
|
typedef struct ConfigItem_badword ConfigItem_badword;
|
|
|
|
struct ConfigItem_badword {
|
|
ConfigItem_badword *prev, *next;
|
|
ConfigFlag flag;
|
|
char *word, *replace;
|
|
unsigned short type;
|
|
char action;
|
|
pcre2_code *pcre2_expr;
|
|
};
|
|
|
|
/*-- end of badwords --*/
|
|
|
|
/* Flags for 'sendflags' in 'sendto_channel' */
|
|
#define SEND_LOCAL 0x1
|
|
#define SEND_REMOTE 0x2
|
|
#define SEND_ALL (SEND_LOCAL|SEND_REMOTE)
|
|
#define SKIP_DEAF 0x4
|
|
#define SKIP_CTCP 0x8
|
|
|
|
typedef struct GeoIPResult GeoIPResult;
|
|
struct GeoIPResult {
|
|
char *country_code;
|
|
char *country_name;
|
|
};
|
|
|
|
typedef enum WhoisConfigDetails {
|
|
WHOIS_CONFIG_DETAILS_DEFAULT = 0,
|
|
WHOIS_CONFIG_DETAILS_NONE = 1,
|
|
WHOIS_CONFIG_DETAILS_LIMITED = 2,
|
|
WHOIS_CONFIG_DETAILS_FULL = 3,
|
|
} WhoisConfigDetails;
|
|
|
|
/* Options for StripControlCodesEx() */
|
|
#define UNRL_STRIP_LOW_ASCII 0x1 /**< Strip all ASCII < 32 (control codes) */
|
|
#define UNRL_STRIP_KEEP_LF 0x2 /**< Do not strip LF (line feed, \n) */
|
|
|
|
/** JSON-RPC API Errors, according to jsonrpc.org spec */
|
|
typedef enum JsonRpcError {
|
|
// Official JSON-RPC error codes:
|
|
JSON_RPC_ERROR_PARSE_ERROR = -32700, /**< JSON parse error (fatal) */
|
|
JSON_RPC_ERROR_INVALID_REQUEST = -32600, /**< Invalid JSON-RPC Request */
|
|
JSON_RPC_ERROR_METHOD_NOT_FOUND = -32601, /**< Method not found */
|
|
JSON_RPC_ERROR_INVALID_PARAMS = -32602, /**< Method parameters invalid */
|
|
JSON_RPC_ERROR_INTERNAL_ERROR = -32603, /**< Internal server error */
|
|
// UnrealIRCd JSON-RPC server specific error codes:
|
|
JSON_RPC_ERROR_API_CALL_DENIED = -32000, /**< The api user does not have enough permissions to do this call */
|
|
JSON_RPC_ERROR_SERVER_GONE = -32001, /**< The request was forwarded to a remote server, but this server went gone while processing the request */
|
|
JSON_RPC_ERROR_TIMEOUT = -32002, /**< The request was forwarded to a remote server, but the request/response timed out (15 seconds) */
|
|
JSON_RPC_ERROR_REMOTE_SERVER_NO_RPC = -32003, /**< The request was going to be forwarded to a remote server, but the remote server does not support JSON-RPC */
|
|
// UnrealIRCd specific application error codes:
|
|
JSON_RPC_ERROR_NOT_FOUND = -1000, /**< Target not found (no such nick / channel / ..) */
|
|
JSON_RPC_ERROR_ALREADY_EXISTS = -1001, /**< Resource already exists by that name (eg on nickchange request, a gline, etc) */
|
|
JSON_RPC_ERROR_INVALID_NAME = -1002, /**< Name is not permitted (eg: nick, channel, ..) */
|
|
JSON_RPC_ERROR_USERNOTINCHANNEL = -1003, /**< The user is not in the channel */
|
|
JSON_RPC_ERROR_TOO_MANY_ENTRIES = -1004, /**< Too many entries (eg: banlist, ..) */
|
|
JSON_RPC_ERROR_DENIED = -1005, /**< Permission denied for user (unrelated to api user permissions) */
|
|
} JsonRpcError;
|
|
|
|
/** Require a parameter in an RPC command */
|
|
#define REQUIRE_PARAM_STRING(name, varname) do { \
|
|
varname = json_object_get_string(params, name); \
|
|
if (!varname) \
|
|
{ \
|
|
rpc_error_fmt(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Missing parameter: '%s'", name); \
|
|
return; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define REQUIRE_PARAM_INTEGER(name, varname) do { \
|
|
json_t *t = json_object_get(params, name); \
|
|
if (!t || !json_is_integer(t)) \
|
|
{ \
|
|
rpc_error_fmt(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Missing parameter: '%s'", name); \
|
|
return; \
|
|
} \
|
|
varname = json_integer_value(t); \
|
|
} while(0)
|
|
|
|
#define REQUIRE_PARAM_BOOLEAN(name, varname) do { \
|
|
json_t *vvv = json_object_get(params, name); \
|
|
if (!v || !json_is_boolean(v)) \
|
|
{ \
|
|
rpc_error_fmt(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Missing parameter: '%s'", name); \
|
|
return; \
|
|
} \
|
|
varname = json_is_true(v) ? 1 : 0; \
|
|
} while(0)
|
|
|
|
#define OPTIONAL_PARAM_STRING(name, varname) varname = json_object_get_string(params, name)
|
|
#define OPTIONAL_PARAM_INTEGER(name, varname, def) varname = json_object_get_integer(params, name, def)
|
|
#define OPTIONAL_PARAM_BOOLEAN(name, varname, def) varname = json_object_get_boolean(params, name, def)
|
|
|
|
#endif /* __struct_include__ */
|
|
|
|
#include "dynconf.h"
|