From e28415f887dba5f12facdd14a0547de037ac6efa Mon Sep 17 00:00:00 2001 From: MrIron Date: Thu, 2 Oct 2025 00:24:33 +0200 Subject: [PATCH 01/13] Added support for LS 302 capabilities and sasl authentication. --- include/capab.h | 27 +- include/client.h | 7 + include/handlers.h | 2 + include/ircd_features.h | 2 + include/msg.h | 4 + include/numeric.h | 17 +- ircd/Makefile.in | 2 + ircd/ircd_features.c | 2 + ircd/m_cap.c | 260 +++++++++---- ircd/m_endburst.c | 2 + ircd/m_xreply.c | 3 + ircd/parse.c | 7 + ircd/s_err.c | 800 ++++++++++++++++++++++++++++++++++++++++ ircd/s_misc.c | 3 + ircd/s_serv.c | 4 + ircd/s_stats.c | 4 + 16 files changed, 1066 insertions(+), 80 deletions(-) diff --git a/include/capab.h b/include/capab.h index 972fd4cd..3599365d 100644 --- a/include/capab.h +++ b/include/capab.h @@ -31,10 +31,13 @@ #include "ircd_features.h" #endif -#define CAPFL_HIDDEN 0x0001 /**< Do not advertize this capability */ -#define CAPFL_PROHIBIT 0x0002 /**< Client may not set this capability */ -#define CAPFL_PROTO 0x0004 /**< Cap must be acknowledged by client */ -#define CAPFL_STICKY 0x0008 /**< Cap may not be cleared once set */ +#define CAPFL_HIDDEN 0x0001 /**< Do not advertize this capability */ +#define CAPFL_HIDDEN_302 0x0002 /**< Do not advertize this capability to users supporting LS 302 */ +#define CAPFL_PROHIBIT 0x0004 /**< Client may not set this capability */ +#define CAPFL_PROTO 0x0008 /**< Cap must be acknowledged by client */ +#define CAPFL_STICKY 0x0010 /**< Cap may not be cleared once set */ +#define CAPFL_STICKY_302 0x0008 /**< Cap may not be cleared once set by users supporting LS 302 */ +#define CAPFL_UNAVAILABLE (CAPFL_HIDDEN | CAPFL_PROHIBIT) #define CAPLIST \ _CAP(ACCOUNTNOTIFY, FEAT_CAP_ACCOUNTNOTIFY, 0, "account-notify"), \ @@ -42,7 +45,9 @@ _CAP(CHGHOST, FEAT_CAP_CHGHOST, 0, "chghost"), \ _CAP(ECHOMESSAGE, FEAT_CAP_ECHOMESSAGE, 0, "echo-message"), \ _CAP(EXTJOIN, FEAT_CAP_EXTJOIN, 0, "extended-join"), \ - _CAP(INVITENOTIFY, FEAT_CAP_INVITENOTIFY, 0, "invite-notify") + _CAP(INVITENOTIFY, FEAT_CAP_INVITENOTIFY, 0, "invite-notify"), \ + _CAP(CAPNOTIFY, 0, CAPFL_HIDDEN_302 | CAPFL_STICKY_302, "cap-notify"), \ + _CAP(SASL, FEAT_CAP_SASL, CAPFL_UNAVAILABLE, "sasl") /** Client capabilities, counting by index. */ enum Capab { @@ -64,4 +69,16 @@ enum CapabBits { #define CapSet(cs, cap) (cs |= cap) #define CapClr(cs, cap) (cs &= ~cap) +/** Set capability value dynamically */ +void cap_set_value(enum Capab cap, const char *value); + +/** Update capability availability and send CAP NEW/DEL as needed */ +void cap_update_availability(enum Capab cap, int available); + +/** Send CAP NEW to clients with cap-notify capability */ +void cap_new(enum Capab cap); + +/** Send CAP DEL to clients with cap-notify capability */ +void cap_del(enum Capab cap); + #endif /* INCLUDED_capab_h */ diff --git a/include/client.h b/include/client.h index 92e4816c..acef7746 100644 --- a/include/client.h +++ b/include/client.h @@ -161,6 +161,7 @@ enum Flag FLAG_LOCOP, /**< Local operator -- SRB */ FLAG_SERVNOTICE, /**< server notices such as kill */ FLAG_OPER, /**< Operator */ + FLAG_SASL, /**< Authenticated using SASL */ FLAG_INVISIBLE, /**< makes user invisible */ FLAG_WALLOP, /**< send wallops to them */ FLAG_DEAF, /**< Makes user deaf */ @@ -169,6 +170,7 @@ enum Flag FLAG_DEBUG, /**< send global debug/anti-hack info */ FLAG_ACCOUNT, /**< account name has been set */ FLAG_HIDDENHOST, /**< user's host is hidden */ + FLAG_CAP302, /**< client supports IRCv3.2 */ FLAG_LAST_FLAG, /**< number of flags */ FLAG_LOCAL_UMODES = FLAG_LOCOP, /**< First local mode flag */ FLAG_GLOBAL_UMODES = FLAG_OPER /**< First global mode flag */ @@ -236,6 +238,7 @@ struct Connection capset_t con_active; /**< Active capabilities (to us) */ struct AuthRequest* con_auth; /**< Auth request for client */ const struct wline* con_wline; /**< WebIRC authorization for client */ + uint64_t con_sasl; /**< SASL session cookie */ }; /** Magic constant to identify valid Connection structures. */ @@ -387,6 +390,8 @@ struct Client { #define cli_wline(cli) con_wline(cli_connect(cli)) /** Get sentalong marker for client. */ #define cli_sentalong(cli) con_sentalong(cli_connect(cli)) +/** Get SASL session cookie for client. */ +#define cli_sasl(cli) con_sasl(cli_connect(cli)) /** Verify that a connection is valid. */ #define con_verify(con) ((con)->con_magic == CONNECTION_MAGIC) @@ -470,6 +475,8 @@ struct Client { #define con_auth(con) ((con)->con_auth) /** Get the WebIRC block (if any) used by the connection. */ #define con_wline(con) ((con)->con_wline) +/** Get the SASL session cookie for the connection. */ +#define con_sasl(con) ((con)->con_sasl) #define STAT_CONNECTING 0x001 /**< connecting to another server */ #define STAT_HANDSHAKE 0x002 /**< pass - server sent */ diff --git a/include/handlers.h b/include/handlers.h index f8bc6073..38361d83 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -124,6 +124,8 @@ extern int m_proto(struct Client*, struct Client*, int, char*[]); extern int m_pseudo(struct Client*, struct Client*, int, char*[]); extern int m_quit(struct Client*, struct Client*, int, char*[]); extern int m_registered(struct Client*, struct Client*, int, char*[]); +extern int m_sasl(struct Client*, struct Client*, int, char*[]); +extern int ms_sasl(struct Client*, struct Client*, int, char*[]); extern int m_silence(struct Client*, struct Client*, int, char*[]); extern int m_stats(struct Client*, struct Client*, int, char*[]); extern int m_time(struct Client*, struct Client*, int, char*[]); diff --git a/include/ircd_features.h b/include/ircd_features.h index 10167947..e77d08e4 100644 --- a/include/ircd_features.h +++ b/include/ircd_features.h @@ -111,6 +111,7 @@ enum Feature { FEAT_CAP_ECHOMESSAGE, FEAT_CAP_EXTJOIN, FEAT_CAP_INVITENOTIFY, + FEAT_CAP_SASL, /* HEAD_IN_SAND Features */ FEAT_HIS_SNOTICES, @@ -139,6 +140,7 @@ enum Feature { FEAT_HIS_STATS_q, FEAT_HIS_STATS_R, FEAT_HIS_STATS_r, + FEAT_HIS_STATS_S, FEAT_HIS_STATS_t, FEAT_HIS_STATS_T, FEAT_HIS_STATS_u, diff --git a/include/msg.h b/include/msg.h index 2fba1e79..e412f09e 100644 --- a/include/msg.h +++ b/include/msg.h @@ -376,6 +376,10 @@ struct Client; #define TOK_CHGHOST "CHGHOST" #define CMD_CHGHOST MSG_CHGHOST, TOK_CHGHOST +#define MSG_AUTHENTICATE "AUTHENTICATE" +#define TOK_AUTHENTICATE "AU" +#define CMD_AUTHENTICATE MSG_AUTHENTICATE, TOK_AUTHENTICATE + /* * Constants */ diff --git a/include/numeric.h b/include/numeric.h index 7da37e91..e436233b 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -468,7 +468,6 @@ extern const struct Numeric* get_error_numeric(int err); /* ERR_NOMANAGER_LONG 565 no longer used */ #define ERR_NOMANAGER 566 /* Undernet extension */ #define ERR_UPASS_SAME_APASS 567 /* Undernet extension */ -#define ERR_LASTERROR 568 /* RPL_LOGON 600 dalnet,unreal RPL_LOGOFF 601 dalnet,unreal @@ -492,4 +491,20 @@ extern const struct Numeric* get_error_numeric(int err); RPL_DUMPRPL 641 unreal RPL_EODUMP 642 unreal */ + +/* + * SASL replies and errors (starting at 900). + */ +#define RPL_LOGGEDIN 900 /* SASL */ +/* RPL_LOGGEDOUT 901 SASL */ +/* ERR_NICKLOCKED 902 SASL */ +#define RPL_SASLSUCCESS 903 /* SASL */ +#define ERR_SASLFAIL 904 /* SASL */ +#define ERR_SASLTOOLONG 905 /* SASL */ +#define ERR_SASLABORTED 906 /* SASL */ +#define ERR_SASLALREADY 907 /* SASL */ +#define RPL_SASLMECHS 908 /* SASL */ + +#define ERR_LASTERROR 909 + #endif /* INCLUDED_numeric_h */ diff --git a/ircd/Makefile.in b/ircd/Makefile.in index 432c66e2..48d0eb34 100644 --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -164,6 +164,7 @@ IRCD_SRC = \ m_restart.c \ m_rping.c \ m_rpong.c \ + m_sasl.c \ m_server.c \ m_set.c \ m_settime.c \ @@ -209,6 +210,7 @@ IRCD_SRC = \ s_serv.c \ s_stats.c \ s_user.c \ + sasl.c \ send.c \ uping.c \ userload.c \ diff --git a/ircd/ircd_features.c b/ircd/ircd_features.c index 6410099b..15f7025a 100644 --- a/ircd/ircd_features.c +++ b/ircd/ircd_features.c @@ -376,6 +376,7 @@ static struct FeatureDesc { F_B(CAP_ECHOMESSAGE, 0, 1, 0), F_B(CAP_EXTJOIN, 0, 1, 0), F_B(CAP_INVITENOTIFY, 0, 1, 0), + F_B(CAP_SASL, 0, 1, 0), /* HEAD_IN_SAND Features */ F_B(HIS_SNOTICES, 0, 1, 0), @@ -404,6 +405,7 @@ static struct FeatureDesc { F_B(HIS_STATS_q, 0, 1, 0), F_B(HIS_STATS_R, 0, 1, 0), F_B(HIS_STATS_r, 0, 1, 0), + F_B(HIS_STATS_S, 0, 1, 0), F_B(HIS_STATS_t, 0, 1, 0), F_B(HIS_STATS_T, 0, 1, 0), F_B(HIS_STATS_u, 0, 0, 0), diff --git a/ircd/m_cap.c b/ircd/m_cap.c index 1709cfd1..593f3253 100644 --- a/ircd/m_cap.c +++ b/ircd/m_cap.c @@ -38,6 +38,7 @@ #include "send.h" #include "s_auth.h" #include "s_user.h" +#include "s_bsd.h" #include #include @@ -51,15 +52,64 @@ static struct capabilities { unsigned long flags; char *name; int namelen; + char value[256]; } capab_list[] = { #define _CAP(cap, config, flags, name) \ - { CAP_ ## cap, #cap, (config), (flags), (name), sizeof(name) - 1 } + { CAP_ ## cap, #cap, (config), (flags), (name), sizeof(name) - 1, "" } CAPLIST #undef _CAP }; #define CAPAB_LIST_LEN (sizeof(capab_list) / sizeof(struct capabilities)) +void cap_set_value(enum Capab cap, const char *value) +{ + if (cap >= _E_CAP_LAST_CAP || !value) + return; + + /* Find the capability in capab_list by bit mask */ + enum CapabBits cap_mask = (1u << cap); + int i; + for (i = 0; i < CAPAB_LIST_LEN; i++) { + if (capab_list[i].cap == cap_mask) { + ircd_strncpy(capab_list[i].value, value, sizeof(capab_list[i].value) - 1); + capab_list[i].value[sizeof(capab_list[i].value) - 1] = '\0'; + return; + } + } +} + +void cap_update_availability(enum Capab cap, int available) +{ + int was_available; + int i; + enum CapabBits cap_mask; + + if (cap >= _E_CAP_LAST_CAP) + return; + + /* Find the capability in capab_list by bit mask */ + cap_mask = (1u << cap); + for (i = 0; i < CAPAB_LIST_LEN; i++) { + if (capab_list[i].cap == cap_mask) { + /* Check previous state by looking at UNAVAILABLE flag */ + was_available = !(capab_list[i].flags & CAPFL_UNAVAILABLE); + + /* If availability changed, update capability visibility */ + if (was_available && !available) { + /* Capability became unavailable - set UNAVAILABLE flag and send CAP DEL */ + capab_list[i].flags |= CAPFL_UNAVAILABLE; + cap_del(cap); + } else if (!was_available && available) { + /* Capability became available - clear UNAVAILABLE flag and send CAP NEW */ + capab_list[i].flags &= ~CAPFL_UNAVAILABLE; + cap_new(cap); + } + return; + } + } +} + static int capab_sort(const struct capabilities *cap1, const struct capabilities *cap2) { @@ -133,8 +183,8 @@ find_cap(const char **caplist_p, int *neg_p) * If more than one line is necessary, each line before the last has * an added "*" parameter before that line's capability list. * @param[in] sptr Client receiving capability list. - * @param[in] set Capabilities to show as set (with ack and sticky modifiers). - * @param[in] rem Capabalities to show as removed (with no other modifier). + * @param[in] set Capabilities to show as set. + * @param[in] rem Capabalities to show as removed. * @param[in] subcmd Name of capability subcommand. */ static int @@ -156,7 +206,11 @@ send_caplist(struct Client *sptr, capset_t set, break; /* Check if the capability is enabled in features() */ - if (!feature_bool(capab_list[i].config)) + if (capab_list[i].config != 0 && !feature_bool(capab_list[i].config)) + continue; + + /* Check if capability is hidden from IRCv3.2 clients */ + if (!set && HasFlag(sptr, FLAG_CAP302) && (flags & CAPFL_HIDDEN_302)) continue; /* This is a little bit subtle, but just involves applying de @@ -169,28 +223,37 @@ send_caplist(struct Client *sptr, capset_t set, && (rem || set || (flags & CAPFL_HIDDEN))) continue; - /* Build the prefix (space separator and any modifiers needed). */ + /* Build the prefix (space separator). */ pfx_len = 0; if (loc) pfx[pfx_len++] = ' '; if (rem && CapHas(rem, capab_list[i].cap)) pfx[pfx_len++] = '-'; - else { - if (flags & CAPFL_PROTO) - pfx[pfx_len++] = '~'; - if (flags & CAPFL_STICKY) - pfx[pfx_len++] = '='; - } pfx[pfx_len] = '\0'; - len = capab_list[i].namelen + pfx_len; /* how much we'd add... */ + /* Get capability value for LS command */ + const char *cap_value = ""; + if (!strcmp(subcmd, "LS")) { + if (capab_list[i].value[0] != '\0' && HasFlag(sptr, FLAG_CAP302)) { + cap_value = capab_list[i].value; + } + } + + /* Calculate length including value */ + int value_len = (cap_value && cap_value[0] != '\0') ? strlen(cap_value) + 1 : 0; /* +1 for = */ + len = capab_list[i].namelen + pfx_len + value_len; /* how much we'd add... */ if (msgq_bufleft(mb) < loc + len + 2) { /* would add too much; must flush */ sendcmdto_one(&me, CMD_CAP, sptr, "%C %s * :%s", sptr, subcmd, capbuf); capbuf[(loc = 0)] = '\0'; /* re-terminate the buffer... */ } - loc += ircd_snprintf(0, capbuf + loc, sizeof(capbuf) - loc, "%s%s", - pfx, capab_list[i].name); + if (cap_value && cap_value[0] != '\0') { + loc += ircd_snprintf(0, capbuf + loc, sizeof(capbuf) - loc, "%s%s=%s", + pfx, capab_list[i].name, cap_value); + } else { + loc += ircd_snprintf(0, capbuf + loc, sizeof(capbuf) - loc, "%s%s", + pfx, capab_list[i].name); + } } msgq_append(0, mb, "%s", capbuf); /* append capabilities to the final cmd */ @@ -205,6 +268,16 @@ cap_ls(struct Client *sptr, const char *caplist) { if (IsUserPort(sptr)) /* registration hasn't completed; suspend it... */ auth_cap_start(cli_auth(sptr)); + + /* Check if client supports IRCv3.2 (LS version >= 302) */ + if (caplist) { + int version = atoi(caplist); + if (version >= 302) { + SetFlag(sptr, FLAG_CAP302); + CapSet(cli_active(sptr), CAP_CAPNOTIFY); + } + } + return send_caplist(sptr, 0, 0, "LS"); /* send list of capabilities */ } @@ -223,9 +296,10 @@ cap_req(struct Client *sptr, const char *caplist) while (cl) { /* walk through the capabilities list... */ if (!(cap = find_cap(&cl, &neg)) /* look up capability... */ - || !feature_bool(cap->config) /* is it deactivated in config? */ + || (cap->config != 0 && !feature_bool(cap->config)) /* is it deactivated in config? */ || (!neg && (cap->flags & CAPFL_PROHIBIT)) /* is it prohibited? */ - || (neg && (cap->flags & CAPFL_STICKY))) { /* is it sticky? */ + || (neg && (cap->flags & CAPFL_STICKY)) /* is it sticky? */ + || (neg && HasFlag(sptr, FLAG_CAP302) && (cap->flags & CAPFL_STICKY_302))) { /* is it sticky for IRCv3.2? */ sendcmdto_one(&me, CMD_CAP, sptr, "%C NAK :%s", sptr, caplist); return 0; /* can't complete requested op... */ } @@ -235,13 +309,13 @@ cap_req(struct Client *sptr, const char *caplist) CapClr(set, cap->cap); CapClr(cs, cap->cap); if (!(cap->flags & CAPFL_PROTO)) - CapClr(as, cap->cap); + CapClr(as, cap->cap); } else { CapClr(rem, cap->cap); CapSet(set, cap->cap); CapSet(cs, cap->cap); if (!(cap->flags & CAPFL_PROTO)) - CapSet(as, cap->cap); + CapSet(as, cap->cap); } } @@ -253,60 +327,6 @@ cap_req(struct Client *sptr, const char *caplist) return 0; } -static int -cap_ack(struct Client *sptr, const char *caplist) -{ - const char *cl = caplist; - struct capabilities *cap; - int neg; - - /* Coming from the client, this generally indicates that the client - * is using a new backwards-incompatible protocol feature. As such, - * it does not require further response from the server. - */ - while (cl) { /* walk through the capabilities list... */ - if (!(cap = find_cap(&cl, &neg)) || /* look up capability... */ - (neg ? HasCap(sptr, cap->cap) : !HasCap(sptr, cap->cap))) /* uh... */ - continue; - - if (neg) { /* set or clear the active capability... */ - if (cap->flags & CAPFL_STICKY) - continue; /* but don't clear sticky capabilities */ - CapClr(cli_active(sptr), cap->cap); - } else { - if (cap->flags & CAPFL_PROHIBIT) - continue; /* and don't set prohibited ones */ - CapSet(cli_active(sptr), cap->cap); - } - } - - return 0; -} - -static int -cap_clear(struct Client *sptr, const char *caplist) -{ - capset_t cleared = 0; - struct capabilities *cap; - unsigned int ii; - - /* XXX: If we ever add a capab list sorted by capab value, it would - * be good cache-wise to use it here. */ - for (ii = 0; ii < CAPAB_LIST_LEN; ++ii) { - cap = &capab_list[ii]; - /* Only clear active non-sticky capabilities. */ - if (!HasCap(sptr, cap->cap) || (cap->flags & CAPFL_STICKY)) - continue; - CapSet(cleared, cap->cap); - CapClr(cli_capab(sptr), cap->cap); - if (!(cap->flags & CAPFL_PROTO)) - CapClr(cli_active(sptr), cap->cap); - } - send_caplist(sptr, 0, cleared, "ACK"); - - return 0; -} - static int cap_end(struct Client *sptr, const char *caplist) { @@ -327,15 +347,107 @@ static struct subcmd { char *cmd; int (*proc)(struct Client *sptr, const char *caplist); } cmdlist[] = { - { "ACK", cap_ack }, - { "CLEAR", cap_clear }, + { "ACK", 0 }, { "END", cap_end }, { "LIST", cap_list }, { "LS", cap_ls }, { "NAK", 0 }, + { "NEW", 0 }, + { "DEL", 0 }, { "REQ", cap_req } }; +/** Send CAP NEW to all clients with cap-notify capability + * @param[in] cap Capability enum value + */ +void cap_new(enum Capab cap) +{ + struct Client* acptr; + int i; + int cap_index = -1; + unsigned long flags; + const char* cap_name = NULL; + const char* cap_value = ""; + + /* Find the capability in the list */ + for (i = 0; i < CAPAB_LIST_LEN; i++) { + if (capab_list[i].cap == (1u << cap)) { + cap_index = i; + cap_name = capab_list[i].name; + cap_value = capab_list[i].value; + flags = capab_list[i].flags; + break; + } + } + + if (cap_index == -1) { + return; + } + + /* Check if the capability should be advertised */ + if (capab_list[cap_index].config != 0 && !feature_bool(capab_list[cap_index].config)) + return; + + /* Iterate through all local clients */ + for (i = 0; i < MAXCONNECTIONS; i++) { + if (!(acptr = LocalClientArray[i])) + continue; + + /* Only send to registered users with cap-notify capability */ + if (!IsUser(acptr) || !MyConnect(acptr) || !CapHas(cli_active(acptr), CAP_CAPNOTIFY)) + continue; + + /* Send CAP NEW message */ + if (cap_value && *cap_value && HasFlag(acptr, FLAG_CAP302)) { + sendcmdto_one(&me, CMD_CAP, acptr, "%C NEW :%s=%s", acptr, cap_name, cap_value); + } else { + sendcmdto_one(&me, CMD_CAP, acptr, "%C NEW :%s", acptr, cap_name); + } + } +} + +/** Send CAP DEL to all clients with cap-notify capability + * @param[in] cap Capability enum value + */ +void cap_del(enum Capab cap) +{ + struct Client* acptr; + int i; + int cap_index = -1; + unsigned long flags; + const char* cap_name = NULL; + + /* Find the capability in the list */ + for (i = 0; i < CAPAB_LIST_LEN; i++) { + if (capab_list[i].cap == (1u << cap)) { + cap_index = i; + cap_name = capab_list[i].name; + flags = capab_list[i].flags; + break; + } + } + + if (cap_index == -1) { + return; + } + + /* Iterate through all local clients */ + for (i = 0; i < MAXCONNECTIONS; i++) { + if (!(acptr = LocalClientArray[i])) + continue; + + /* Only send to registered users with cap-notify capability */ + if (!IsUser(acptr) || !MyConnect(acptr) || !CapHas(cli_active(acptr), CAP_CAPNOTIFY)) + continue; + + /* Send CAP DEL message */ + sendcmdto_one(&me, CMD_CAP, acptr, "%C DEL :%s", acptr, cap_name); + + /* Disable the capability for this client. */ + CapClr(cli_active(acptr), capab_list[cap_index].cap); + } +} + static int subcmd_search(const char *cmd, const struct subcmd *elem) { diff --git a/ircd/m_endburst.c b/ircd/m_endburst.c index 46d51ae0..15fd6e4b 100644 --- a/ircd/m_endburst.c +++ b/ircd/m_endburst.c @@ -92,6 +92,7 @@ #include "numeric.h" #include "numnicks.h" #include "send.h" +#include "sasl.h" /* #include -- Now using assert in ircd_log.h */ @@ -154,6 +155,7 @@ int ms_end_of_burst_ack(struct Client *cptr, struct Client *sptr, int parc, char sptr); sendcmdto_serv_butone(sptr, CMD_END_OF_BURST_ACK, cptr, ""); ClearBurstAck(sptr); + sasl_check_capability(); return 0; } diff --git a/ircd/m_xreply.c b/ircd/m_xreply.c index f4323d97..fffd61e2 100644 --- a/ircd/m_xreply.c +++ b/ircd/m_xreply.c @@ -90,6 +90,7 @@ #include "numnicks.h" #include "s_auth.h" #include "send.h" +#include "sasl.h" #include @@ -129,6 +130,8 @@ int ms_xreply(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) /* OK, figure out where to route the message */ if (!ircd_strncmp("iauth:", routing, 6)) auth_send_xreply(sptr, routing + 6, reply); + else if (!ircd_strncmp("sasl:", routing, 5)) + sasl_send_xreply(sptr, routing + 5, reply); else /* If we don't know where to route it, log it and drop it */ log_write(LS_SYSTEM, L_NOTICE, 0, "Received unroutable extension reply " diff --git a/ircd/parse.c b/ircd/parse.c index cfc78ca3..061792c4 100644 --- a/ircd/parse.c +++ b/ircd/parse.c @@ -658,6 +658,13 @@ struct Message msgtab[] = { /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_quit, m_ignore, m_ignore, m_ignore, m_ignore } }, + { + MSG_AUTHENTICATE, + TOK_AUTHENTICATE, + 0, MAXPARA, 0, 0, NULL, + /* UNREG, CLIENT, SERVER, OPER, SERVICE */ + { m_sasl, m_sasl, ms_sasl, m_sasl, m_ignore } + }, { 0 } }; diff --git a/ircd/s_err.c b/ircd/s_err.c index 3390ce12..65b60ad7 100644 --- a/ircd/s_err.c +++ b/ircd/s_err.c @@ -1230,6 +1230,806 @@ static Numeric replyTable[] = { /* 598 */ { 0 }, /* 599 */ + { 0 }, +/* 600 */ + { 0 }, +/* 601 */ + { 0 }, +/* 602 */ + { 0 }, +/* 603 */ + { 0 }, +/* 604 */ + { 0 }, +/* 605 */ + { 0 }, +/* 606 */ + { 0 }, +/* 607 */ + { 0 }, +/* 608 */ + { 0 }, +/* 609 */ + { 0 }, +/* 610 */ + { 0 }, +/* 611 */ + { 0 }, +/* 612 */ + { 0 }, +/* 613 */ + { 0 }, +/* 614 */ + { 0 }, +/* 615 */ + { 0 }, +/* 616 */ + { 0 }, +/* 617 */ + { 0 }, +/* 618 */ + { 0 }, +/* 619 */ + { 0 }, +/* 620 */ + { 0 }, +/* 621 */ + { 0 }, +/* 622 */ + { 0 }, +/* 623 */ + { 0 }, +/* 624 */ + { 0 }, +/* 625 */ + { 0 }, +/* 626 */ + { 0 }, +/* 627 */ + { 0 }, +/* 628 */ + { 0 }, +/* 629 */ + { 0 }, +/* 630 */ + { 0 }, +/* 631 */ + { 0 }, +/* 632 */ + { 0 }, +/* 633 */ + { 0 }, +/* 634 */ + { 0 }, +/* 635 */ + { 0 }, +/* 636 */ + { 0 }, +/* 637 */ + { 0 }, +/* 638 */ + { 0 }, +/* 639 */ + { 0 }, +/* 640 */ + { 0 }, +/* 641 */ + { 0 }, +/* 642 */ + { 0 }, +/* 643 */ + { 0 }, +/* 644 */ + { 0 }, +/* 645 */ + { 0 }, +/* 646 */ + { 0 }, +/* 647 */ + { 0 }, +/* 648 */ + { 0 }, +/* 649 */ + { 0 }, +/* 650 */ + { 0 }, +/* 651 */ + { 0 }, +/* 652 */ + { 0 }, +/* 653 */ + { 0 }, +/* 654 */ + { 0 }, +/* 655 */ + { 0 }, +/* 656 */ + { 0 }, +/* 657 */ + { 0 }, +/* 658 */ + { 0 }, +/* 659 */ + { 0 }, +/* 660 */ + { 0 }, +/* 667 */ + { 0 }, +/* 668 */ + { 0 }, +/* 669 */ + { 0 }, +/* 664 */ + { 0 }, +/* 665 */ + { 0 }, +/* 666 */ + { 0 }, +/* 667 */ + { 0 }, +/* 668 */ + { 0 }, +/* 669 */ + { 0 }, +/* 670 */ + { 0 }, +/* 671 */ + { 0 }, +/* 672 */ + { 0 }, +/* 673 */ + { 0 }, +/* 674 */ + { 0 }, +/* 675 */ + { 0 }, +/* 676 */ + { 0 }, +/* 677 */ + { 0 }, +/* 678 */ + { 0 }, +/* 679 */ + { 0 }, +/* 680 */ + { 0 }, +/* 681 */ + { 0 }, +/* 682 */ + { 0 }, +/* 683 */ + { 0 }, +/* 684 */ + { 0 }, +/* 685 */ + { 0 }, +/* 686 */ + { 0 }, +/* 687 */ + { 0 }, +/* 688 */ + { 0 }, +/* 689 */ + { 0 }, +/* 690 */ + { 0 }, +/* 691 */ + { 0 }, +/* 692 */ + { 0 }, +/* 693 */ + { 0 }, +/* 694 */ + { 0 }, +/* 695 */ + { 0 }, +/* 696 */ + { 0 }, +/* 697 */ + { 0 }, +/* 698 */ + { 0 }, +/* 699 */ + { 0 }, +/* 700 */ + { 0 }, +/* 701 */ + { 0 }, +/* 702 */ + { 0 }, +/* 703 */ + { 0 }, +/* 704 */ + { 0 }, +/* 705 */ + { 0 }, +/* 707 */ + { 0 }, +/* 707 */ + { 0 }, +/* 708 */ + { 0 }, +/* 709 */ + { 0 }, +/* 710 */ + { 0 }, +/* 711 */ + { 0 }, +/* 712 */ + { 0 }, +/* 713 */ + { 0 }, +/* 714 */ + { 0 }, +/* 715 */ + { 0 }, +/* 717 */ + { 0 }, +/* 717 */ + { 0 }, +/* 718 */ + { 0 }, +/* 719 */ + { 0 }, +/* 720 */ + { 0 }, +/* 721 */ + { 0 }, +/* 722 */ + { 0 }, +/* 723 */ + { 0 }, +/* 724 */ + { 0 }, +/* 725 */ + { 0 }, +/* 727 */ + { 0 }, +/* 727 */ + { 0 }, +/* 728 */ + { 0 }, +/* 729 */ + { 0 }, +/* 730 */ + { 0 }, +/* 731 */ + { 0 }, +/* 732 */ + { 0 }, +/* 733 */ + { 0 }, +/* 734 */ + { 0 }, +/* 735 */ + { 0 }, +/* 737 */ + { 0 }, +/* 737 */ + { 0 }, +/* 738 */ + { 0 }, +/* 739 */ + { 0 }, +/* 740 */ + { 0 }, +/* 741 */ + { 0 }, +/* 742 */ + { 0 }, +/* 743 */ + { 0 }, +/* 744 */ + { 0 }, +/* 745 */ + { 0 }, +/* 747 */ + { 0 }, +/* 747 */ + { 0 }, +/* 748 */ + { 0 }, +/* 749 */ + { 0 }, +/* 750 */ + { 0 }, +/* 751 */ + { 0 }, +/* 752 */ + { 0 }, +/* 753 */ + { 0 }, +/* 754 */ + { 0 }, +/* 755 */ + { 0 }, +/* 757 */ + { 0 }, +/* 757 */ + { 0 }, +/* 758 */ + { 0 }, +/* 759 */ + { 0 }, +/* 770 */ + { 0 }, +/* 777 */ + { 0 }, +/* 778 */ + { 0 }, +/* 779 */ + { 0 }, +/* 774 */ + { 0 }, +/* 775 */ + { 0 }, +/* 777 */ + { 0 }, +/* 777 */ + { 0 }, +/* 778 */ + { 0 }, +/* 779 */ + { 0 }, +/* 770 */ + { 0 }, +/* 771 */ + { 0 }, +/* 772 */ + { 0 }, +/* 773 */ + { 0 }, +/* 774 */ + { 0 }, +/* 775 */ + { 0 }, +/* 777 */ + { 0 }, +/* 777 */ + { 0 }, +/* 778 */ + { 0 }, +/* 779 */ + { 0 }, +/* 780 */ + { 0 }, +/* 781 */ + { 0 }, +/* 782 */ + { 0 }, +/* 783 */ + { 0 }, +/* 784 */ + { 0 }, +/* 785 */ + { 0 }, +/* 787 */ + { 0 }, +/* 787 */ + { 0 }, +/* 788 */ + { 0 }, +/* 789 */ + { 0 }, +/* 790 */ + { 0 }, +/* 791 */ + { 0 }, +/* 792 */ + { 0 }, +/* 793 */ + { 0 }, +/* 794 */ + { 0 }, +/* 795 */ + { 0 }, +/* 797 */ + { 0 }, +/* 797 */ + { 0 }, +/* 798 */ + { 0 }, +/* 799 */ + { 0 }, +/* 800 */ + { 0 }, +/* 801 */ + { 0 }, +/* 802 */ + { 0 }, +/* 803 */ + { 0 }, +/* 804 */ + { 0 }, +/* 805 */ + { 0 }, +/* 808 */ + { 0 }, +/* 807 */ + { 0 }, +/* 808 */ + { 0 }, +/* 809 */ + { 0 }, +/* 810 */ + { 0 }, +/* 811 */ + { 0 }, +/* 812 */ + { 0 }, +/* 813 */ + { 0 }, +/* 814 */ + { 0 }, +/* 815 */ + { 0 }, +/* 818 */ + { 0 }, +/* 817 */ + { 0 }, +/* 818 */ + { 0 }, +/* 819 */ + { 0 }, +/* 820 */ + { 0 }, +/* 821 */ + { 0 }, +/* 822 */ + { 0 }, +/* 823 */ + { 0 }, +/* 824 */ + { 0 }, +/* 825 */ + { 0 }, +/* 828 */ + { 0 }, +/* 827 */ + { 0 }, +/* 828 */ + { 0 }, +/* 829 */ + { 0 }, +/* 830 */ + { 0 }, +/* 831 */ + { 0 }, +/* 832 */ + { 0 }, +/* 833 */ + { 0 }, +/* 834 */ + { 0 }, +/* 835 */ + { 0 }, +/* 838 */ + { 0 }, +/* 837 */ + { 0 }, +/* 838 */ + { 0 }, +/* 839 */ + { 0 }, +/* 840 */ + { 0 }, +/* 841 */ + { 0 }, +/* 842 */ + { 0 }, +/* 843 */ + { 0 }, +/* 844 */ + { 0 }, +/* 845 */ + { 0 }, +/* 848 */ + { 0 }, +/* 847 */ + { 0 }, +/* 848 */ + { 0 }, +/* 849 */ + { 0 }, +/* 850 */ + { 0 }, +/* 851 */ + { 0 }, +/* 852 */ + { 0 }, +/* 853 */ + { 0 }, +/* 854 */ + { 0 }, +/* 855 */ + { 0 }, +/* 858 */ + { 0 }, +/* 857 */ + { 0 }, +/* 858 */ + { 0 }, +/* 859 */ + { 0 }, +/* 880 */ + { 0 }, +/* 887 */ + { 0 }, +/* 888 */ + { 0 }, +/* 889 */ + { 0 }, +/* 884 */ + { 0 }, +/* 885 */ + { 0 }, +/* 888 */ + { 0 }, +/* 887 */ + { 0 }, +/* 888 */ + { 0 }, +/* 889 */ + { 0 }, +/* 870 */ + { 0 }, +/* 871 */ + { 0 }, +/* 872 */ + { 0 }, +/* 873 */ + { 0 }, +/* 874 */ + { 0 }, +/* 875 */ + { 0 }, +/* 878 */ + { 0 }, +/* 877 */ + { 0 }, +/* 878 */ + { 0 }, +/* 879 */ + { 0 }, +/* 880 */ + { 0 }, +/* 881 */ + { 0 }, +/* 882 */ + { 0 }, +/* 883 */ + { 0 }, +/* 884 */ + { 0 }, +/* 885 */ + { 0 }, +/* 888 */ + { 0 }, +/* 887 */ + { 0 }, +/* 888 */ + { 0 }, +/* 889 */ + { 0 }, +/* 890 */ + { 0 }, +/* 891 */ + { 0 }, +/* 892 */ + { 0 }, +/* 893 */ + { 0 }, +/* 894 */ + { 0 }, +/* 895 */ + { 0 }, +/* 898 */ + { 0 }, +/* 897 */ + { 0 }, +/* 898 */ + { 0 }, +/* 899 */ + { 0 }, +/* 900 */ + { RPL_LOGGEDIN, "%s!%s@%s %s :You are now logged in as %s", "900" }, +/* 901 */ + { 0 }, +/* 902 */ + { 0 }, +/* 903 */ + { RPL_SASLSUCCESS, ":SASL authentication successful", "903" }, +/* 904 */ + { ERR_SASLFAIL, ":%s", "904" }, +/* 905 */ + { ERR_SASLTOOLONG, ":SASL message too long", "905" }, +/* 909 */ + { ERR_SASLABORTED, ":SASL authentication aborted", "906" }, +/* 907 */ + { ERR_SASLALREADY, ":You have already authenticated using SASL", "907" }, +/* 908 */ + { RPL_SASLMECHS, "%s :are available SASL mechanisms", "908" }, +/* 909 */ + { 0 }, +/* 910 */ + { 0 }, +/* 911 */ + { 0 }, +/* 912 */ + { 0 }, +/* 913 */ + { 0 }, +/* 914 */ + { 0 }, +/* 915 */ + { 0 }, +/* 919 */ + { 0 }, +/* 917 */ + { 0 }, +/* 918 */ + { 0 }, +/* 919 */ + { 0 }, +/* 920 */ + { 0 }, +/* 921 */ + { 0 }, +/* 922 */ + { 0 }, +/* 923 */ + { 0 }, +/* 924 */ + { 0 }, +/* 925 */ + { 0 }, +/* 929 */ + { 0 }, +/* 927 */ + { 0 }, +/* 928 */ + { 0 }, +/* 929 */ + { 0 }, +/* 930 */ + { 0 }, +/* 931 */ + { 0 }, +/* 932 */ + { 0 }, +/* 933 */ + { 0 }, +/* 934 */ + { 0 }, +/* 935 */ + { 0 }, +/* 939 */ + { 0 }, +/* 937 */ + { 0 }, +/* 938 */ + { 0 }, +/* 939 */ + { 0 }, +/* 940 */ + { 0 }, +/* 941 */ + { 0 }, +/* 942 */ + { 0 }, +/* 943 */ + { 0 }, +/* 944 */ + { 0 }, +/* 945 */ + { 0 }, +/* 949 */ + { 0 }, +/* 947 */ + { 0 }, +/* 948 */ + { 0 }, +/* 949 */ + { 0 }, +/* 950 */ + { 0 }, +/* 951 */ + { 0 }, +/* 952 */ + { 0 }, +/* 953 */ + { 0 }, +/* 954 */ + { 0 }, +/* 955 */ + { 0 }, +/* 959 */ + { 0 }, +/* 957 */ + { 0 }, +/* 958 */ + { 0 }, +/* 959 */ + { 0 }, +/* 990 */ + { 0 }, +/* 997 */ + { 0 }, +/* 998 */ + { 0 }, +/* 999 */ + { 0 }, +/* 994 */ + { 0 }, +/* 995 */ + { 0 }, +/* 999 */ + { 0 }, +/* 997 */ + { 0 }, +/* 998 */ + { 0 }, +/* 999 */ + { 0 }, +/* 970 */ + { 0 }, +/* 971 */ + { 0 }, +/* 972 */ + { 0 }, +/* 973 */ + { 0 }, +/* 974 */ + { 0 }, +/* 975 */ + { 0 }, +/* 979 */ + { 0 }, +/* 977 */ + { 0 }, +/* 978 */ + { 0 }, +/* 979 */ + { 0 }, +/* 980 */ + { 0 }, +/* 981 */ + { 0 }, +/* 982 */ + { 0 }, +/* 983 */ + { 0 }, +/* 984 */ + { 0 }, +/* 985 */ + { 0 }, +/* 989 */ + { 0 }, +/* 987 */ + { 0 }, +/* 988 */ + { 0 }, +/* 989 */ + { 0 }, +/* 990 */ + { 0 }, +/* 991 */ + { 0 }, +/* 992 */ + { 0 }, +/* 993 */ + { 0 }, +/* 994 */ + { 0 }, +/* 995 */ + { 0 }, +/* 999 */ + { 0 }, +/* 997 */ + { 0 }, +/* 998 */ + { 0 }, +/* 999 */ { 0 } }; diff --git a/ircd/s_misc.c b/ircd/s_misc.c index a6a0cff3..f2cec5b0 100644 --- a/ircd/s_misc.c +++ b/ircd/s_misc.c @@ -57,6 +57,7 @@ #include "sys.h" #include "uping.h" #include "userload.h" +#include "sasl.h" /* #include -- Now using assert in ircd_log.h */ #include @@ -251,6 +252,8 @@ static void exit_one_client(struct Client* bcptr, const char* comment) Count_serverdisconnects(UserStats); else Count_remoteserverquits(UserStats); + + sasl_check_capability(); } else if (IsMe(bcptr)) { diff --git a/ircd/s_serv.c b/ircd/s_serv.c index 2969808b..662f6302 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -57,6 +57,7 @@ #include "struct.h" #include "sys.h" #include "userload.h" +#include "sasl.h" /* #include -- Now using assert in ircd_log.h */ #include @@ -197,6 +198,9 @@ int server_estab(struct Client *cptr, struct ConfItem *aconf) gline_burst(cptr); jupe_burst(cptr); + /* Burst SASL configuration. */ + sasl_burst(cptr); + /* * Pass on my client information to the new server * diff --git a/ircd/s_stats.c b/ircd/s_stats.c index 07ddf9cb..4f5af674 100644 --- a/ircd/s_stats.c +++ b/ircd/s_stats.c @@ -51,6 +51,7 @@ #include "s_serv.h" #include "s_stats.h" #include "s_user.h" +#include "sasl.h" #include "send.h" #include "struct.h" #include "userload.h" @@ -619,6 +620,9 @@ struct StatDesc statsinfo[] = { send_usage, 0, "System resource usage (Debug only)." }, #endif + { 'S', "sasl", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_S, + sasl_stats, 0, + "SASL authentication statistics." }, { 'T', "motds", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_T, motd_report, 0, "Configured Message Of The Day files." }, From 12fbda5edbf31e10da8d7e708c9d8e1ac01059ea Mon Sep 17 00:00:00 2001 From: MrIron Date: Thu, 2 Oct 2025 00:27:30 +0200 Subject: [PATCH 02/13] fix --- include/capab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/capab.h b/include/capab.h index 3599365d..120895ab 100644 --- a/include/capab.h +++ b/include/capab.h @@ -36,7 +36,7 @@ #define CAPFL_PROHIBIT 0x0004 /**< Client may not set this capability */ #define CAPFL_PROTO 0x0008 /**< Cap must be acknowledged by client */ #define CAPFL_STICKY 0x0010 /**< Cap may not be cleared once set */ -#define CAPFL_STICKY_302 0x0008 /**< Cap may not be cleared once set by users supporting LS 302 */ +#define CAPFL_STICKY_302 0x0020 /**< Cap may not be cleared once set by users supporting LS 302 */ #define CAPFL_UNAVAILABLE (CAPFL_HIDDEN | CAPFL_PROHIBIT) #define CAPLIST \ From e1c0d2fe0e4389e4d378e9a8e1f57fe1891e38cb Mon Sep 17 00:00:00 2001 From: MrIron Date: Thu, 2 Oct 2025 00:55:36 +0200 Subject: [PATCH 03/13] Added missing new files. --- include/sasl.h | 43 +++++++ ircd/m_sasl.c | 189 ++++++++++++++++++++++++++++ ircd/sasl.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 564 insertions(+) create mode 100644 include/sasl.h create mode 100644 ircd/m_sasl.c create mode 100644 ircd/sasl.c diff --git a/include/sasl.h b/include/sasl.h new file mode 100644 index 00000000..c167a769 --- /dev/null +++ b/include/sasl.h @@ -0,0 +1,43 @@ +#ifndef INCLUDED_sasl_h +#define INCLUDED_sasl_h +/* + * IRC - Internet Relay Chat, include/sasl.h + * Copyright (C) 2025 MrIron + * + * 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. + */ + +/** @file + * @brief SASL authentication support + */ + +#ifndef INCLUDED_time_h +#include +#define INCLUDED_time_h +#endif + +struct Client; +struct StatDesc; + +/* Public SASL functions */ +extern int sasl_available(void); +extern const char* sasl_get_server(void); +extern const char* sasl_get_mechanisms(void); +extern int sasl_mechanism_supported(const char* mechanism); +extern void sasl_update_configuration(time_t timestamp, const char* server, const char* mechanisms); +extern time_t sasl_get_timestamp(void); +extern void sasl_burst(struct Client* cptr); +extern void sasl_check_capability(void); +extern void sasl_send_xreply(struct Client* sptr, const char* routing, const char* reply); +extern struct Client* find_sasl_client(unsigned long cookie); +extern void sasl_stats(struct Client* sptr, const struct StatDesc* sd, char* param); + +#endif /* INCLUDED_sasl_h */ \ No newline at end of file diff --git a/ircd/m_sasl.c b/ircd/m_sasl.c new file mode 100644 index 00000000..a822fe19 --- /dev/null +++ b/ircd/m_sasl.c @@ -0,0 +1,189 @@ +/* + * IRC - Internet Relay Chat, ircd/m_sasl.c + * Copyright (C) 2025 MrIron + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * m_functions execute protocol messages on this server: + * + * cptr is always NON-NULL, pointing to a *LOCAL* client + * structure (with an open socket connected!). This + * identifies the physical socket where the message + * originated (or which caused the m_function to be + * executed--some m_functions may call others...). + * + * sptr is the source of the message, defined by the + * prefix part of the message if present. If not + * or prefix not found, then sptr==cptr. + * + * (!IsServer(cptr)) => (cptr == sptr), because + * prefixes are taken *only* from servers... + * + * (IsServer(cptr)) + * (sptr == cptr) => the message didn't + * have the prefix. + * + * (sptr != cptr && IsServer(sptr) means + * the prefix specified servername. (?) + * + * (sptr != cptr && !IsServer(sptr) means + * that message originated from a remote + * user (not local). + * + * combining + * + * (!IsServer(sptr)) means that, sptr can safely + * taken as defining the target structure of the + * message in this server. + * + * *Always* true (if 'parse' and others are working correct): + * + * 1) sptr->from == cptr (note: cptr->from == cptr) + * + * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr + * *cannot* be a local connection, unless it's + * actually cptr!). [MyConnect(x) should probably + * be defined as (x == x->from) --msa ] + * + * parc number of variable parameter strings (if zero, + * parv is allowed to be NULL) + * + * parv a NULL terminated list of parameter pointers, + * + * parv[0], sender (prefix string), if not present + * this points to an empty string. + * parv[1]...parv[parc-1] + * pointers to additional parameters + * parv[parc] == NULL, *always* + * + * note: it is guaranteed that parv[0]..parv[parc-1] are all + * non-NULL pointers. + */ +#include "config.h" + +#include "client.h" +#include "ircd.h" +#include "ircd_reply.h" +#include "ircd_string.h" +#include "msg.h" +#include "numeric.h" +#include "numnicks.h" +#include "sasl.h" +#include "send.h" + +#include + +int m_sasl(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) +{ + struct Client* acptr; + static uint64_t routing_ticker = 0; + + if (parc < 2 || *parv[1] == '\0') + return need_more_params(sptr, "AUTHENTICATE"); + + if (!CapHas(cli_active(cptr), CAP_SASL)) + return 0; + + if (HasFlag(sptr, FLAG_SASL) || HasFlag(sptr, FLAG_ACCOUNT)) + return send_reply(cptr, ERR_SASLALREADY); + + acptr = find_match_server((char*)sasl_get_server()); + if (!sasl_available() || !acptr) + return send_reply(cptr, ERR_SASLFAIL, "The login server is currently disconnected. Please excuse the inconvenience."); + + if (strlen(parv[1]) > 400) + return send_reply(cptr, ERR_SASLTOOLONG); + + if (strcmp(parv[1], "*") == 0) { + send_reply(cptr, ERR_SASLABORTED); + cli_sasl(cptr) = 0; + return 0; + } + + /* Is this the initial authentication challenge? */ + if (!cli_sasl(cptr)) { + if (!sasl_mechanism_supported(parv[1])) + return send_reply(cptr, RPL_SASLMECHS, sasl_get_mechanisms()); + + cli_sasl(cptr) = ++routing_ticker; + + /* Is the user already registered? We then send the NumNick. */ + if (IsUser(cptr)) { + sendcmdto_one(&me, CMD_XQUERY, acptr, "%C sasl:%lu :SASL %s%s %s", + acptr, cli_sasl(cptr), NumNick(cptr), parv[1]); + } else { + /* If not, we pass on the IP and fingerprint. */ + sendcmdto_one(&me, CMD_XQUERY, acptr, "%C sasl:%lu :SASL %s %s %s", + acptr, cli_sasl(cptr), ircd_ntoa(&cli_ip(cptr)), + /*cli_fingerprint(cptr) ? cli_fingerprint(cptr) : */"_", + parv[1]); + } + } else { + sendcmdto_one(&me, CMD_XQUERY, acptr, "%C sasl:%lu :SASL %s", + acptr, cli_sasl(cptr), parv[1]); + } + + return 0; +} + +/** Handler for configuring the SASL authentication layer on the network + * @param[in] cptr Local client that sent us the message + * @param[in] sptr Original source of the message + * @param[in] parc Number of parameters + * @param[in] parv Parameter vector + * @return 0 on success + */ +int ms_sasl(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) +{ + time_t timestamp; + struct Client* acptr; + + if (parc < 2) + return need_more_params(sptr, "AU"); + + /* Check if this is a configuration message */ + if (parv[1][0] == '=') { + /* Format: AU = */ + if (parc < 5) + return need_more_params(sptr, "AU"); + + timestamp = atoi(parv[2]); + if (timestamp > sasl_get_timestamp() || !sasl_get_server()) { + const char* old_server = sasl_get_server(); + const char* old_mechanisms = sasl_get_mechanisms(); + + sasl_update_configuration(timestamp, parv[3], parv[4]); + sendcmdto_serv_butone(sptr, CMD_AUTHENTICATE, cptr, "= %s %s %s", + parv[2], parv[3], parv[4]); + + /* Only send opmask if there was actually a change */ + if (!old_server || !old_mechanisms || + ircd_strcmp(old_server, parv[3]) != 0 || + ircd_strcmp(old_mechanisms, parv[4]) != 0) { + sendto_opmask_butone(0, SNO_NETWORK, + "SASL authentication layer is %s accepting %s", + parv[3], parv[4]); + } + } + } + + return 0; +} \ No newline at end of file diff --git a/ircd/sasl.c b/ircd/sasl.c new file mode 100644 index 00000000..055360e0 --- /dev/null +++ b/ircd/sasl.c @@ -0,0 +1,332 @@ +/* + * IRC - Internet Relay Chat, ircd/sasl.c + * Copyright (C) 2025 MrIron + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** @file + * @brief SASL authentication implementation + */ + +#include "config.h" + +#include "sasl.h" +#include "client.h" +#include "ircd.h" +#include "ircd_alloc.h" +#include "ircd_string.h" +#include "ircd_reply.h" +#include "send.h" +#include "msg.h" +#include "capab.h" +#include "numnicks.h" +#include "s_debug.h" +#include "s_bsd.h" +#include "numeric.h" + +#include + +/** SASL server information */ +struct SaslServer { + time_t timestamp; /**< Timestamp of the AU configuration */ + char *server; /**< Server name providing SASL */ + char *mechanisms; /**< Comma-delimited list of supported mechanisms */ + unsigned long auth_success; /**< Number of successful authentications */ + unsigned long auth_failed; /**< Number of failed authentications */ +}; + +/** Global SASL server info - only one allowed */ +static struct SaslServer sasl_server = { 0, NULL, NULL, 0, 0 }; + +/** Check if SASL is available + * @return 1 if SASL server is configured, 0 otherwise + */ +int sasl_available(void) +{ + if (sasl_server.server == NULL + || sasl_server.mechanisms == NULL + || !find_match_server((char*)sasl_get_server())) + return 0; + + return 1; +} + +/** Get the current SASL server name + * @return Server name or NULL if none set + */ +const char* sasl_get_server(void) +{ + return sasl_server.server; +} + +/** Get the current SASL mechanisms + * @return Comma-delimited mechanism list or NULL if none set + */ +const char* sasl_get_mechanisms(void) +{ + return sasl_server.mechanisms; +} + +/** Check if a mechanism exists in a mechanism list + * @param[in] mechanism The mechanism to find + * @param[in] mechanism_list Comma-delimited list of mechanisms + * @return 1 if found, 0 if not + */ +static int mechanism_in_list(const char* mechanism, const char* mechanism_list) +{ + char* mech_list; + char* token; + int found = 0; + + if (!mechanism_list || !*mechanism_list || !mechanism || !*mechanism) + return 0; + + DupString(mech_list, mechanism_list); + if (!mech_list) + return 0; + + token = strtok(mech_list, ","); + while (token) { + /* Trim whitespace */ + while (*token == ' ') token++; + char* end = token + strlen(token) - 1; + while (end > token && *end == ' ') *end-- = '\0'; + + if (ircd_strcmp(token, mechanism) == 0) { + found = 1; + break; + } + token = strtok(NULL, ","); + } + + MyFree(mech_list); + return found; +} + +/** Check if a SASL mechanism is supported + * @param[in] mechanism The mechanism to check + * @return 1 if supported, 0 if not + */ +int sasl_mechanism_supported(const char* mechanism) +{ + return mechanism_in_list(mechanism, sasl_server.mechanisms); +} + +/** Update SASL configuration + * @param[in] timestamp Timestamp from AU message + * @param[in] server Server name + * @param[in] mechanisms Comma-delimited mechanism list + */ +void sasl_update_configuration(time_t timestamp, const char* server, const char* mechanisms) +{ + /* Free old data */ + if (sasl_server.server) { + MyFree(sasl_server.server); + sasl_server.server = NULL; + } + if (sasl_server.mechanisms) { + MyFree(sasl_server.mechanisms); + sasl_server.mechanisms = NULL; + } + + /* Set new data */ + sasl_server.timestamp = timestamp; + DupString(sasl_server.server, server); + DupString(sasl_server.mechanisms, mechanisms); + + /* Update capability information */ + cap_set_value(E_CAP_SASL, sasl_server.mechanisms); + + /* Check if SASL capability availability changed */ + sasl_check_capability(); +} + +/** Get SASL server timestamp + * @return Timestamp of current SASL server info + */ +time_t sasl_get_timestamp(void) +{ + return sasl_server.timestamp; +} + +/** Burst SASL server information to a newly connected server + * @param[in] cptr Server to send AU message to + */ +void sasl_burst(struct Client* cptr) +{ + if (sasl_server.server && sasl_server.mechanisms) { + sendcmdto_one(&me, CMD_AUTHENTICATE, cptr, "= %Tu %s %s", + sasl_server.timestamp, + sasl_server.server, + sasl_server.mechanisms); + } +} + +/** Check and update SASL capability availability + * This function should be called when events occur that might change + * SASL availability (netjoin/netsplit, AU messages) + */ +void sasl_check_capability(void) +{ + cap_update_availability(E_CAP_SASL, sasl_available()); +} + +/** Find a client by their SASL session cookie + * @param[in] cookie SASL session cookie to search for + * @return Client with matching SASL cookie, or NULL if not found + */ +struct Client* find_sasl_client(unsigned long cookie) +{ + struct Client* cptr; + int i; + + if (!cookie) + return NULL; + + /* Search through all local clients */ + for (i = 0; i < MAXCONNECTIONS; i++) { + if (!(cptr = LocalClientArray[i])) + continue; + + /* Check if this client has the matching SASL cookie */ + if (cli_sasl(cptr) == cookie) + return cptr; + } + + return NULL; +} + +/** Handle SASL extension reply from authentication server + * @param[in] sptr Server that sent the reply + * @param[in] routing Routing information (should be SASL cookie) + * @param[in] reply The SASL reply message + */ +void sasl_send_xreply(struct Client* sptr, const char* routing, const char* reply) +{ + struct Client* cli; + unsigned long cookie; + + if (!routing || !reply) + return; + + /* Parse the routing information to get the SASL cookie */ + cookie = strtoul(routing, NULL, 10); + if (!cookie) { + Debug((DEBUG_DEBUG, "sasl_send_xreply: Invalid cookie in routing '%s'", routing)); + return; + } + + /* Find the client with this SASL cookie */ + cli = find_sasl_client(cookie); + if (!cli) { + Debug((DEBUG_DEBUG, "sasl_send_xreply: No client found for SASL cookie %lu", cookie)); + return; + } + + if (reply[0] == 'O' && reply[1] == 'K' + && (reply[2] == '\0' || reply[2] == ' ')) { + + const char *account_info = reply + 3; /* Skip "OK " */ + char *account_copy, *username, *id_str, *flags_str, *extra; + + if (!IsUser(cli)) { + /* Parse account information: username:id:flags */ + DupString(account_copy, account_info); + if (!account_copy) + return; + + username = strtok(account_copy, ":"); + id_str = strtok(NULL, ":"); + flags_str = strtok(NULL, " "); + extra = strtok(NULL, ""); + + /* Copy account name to User structure */ + ircd_strncpy(cli_user(cli)->account, username, ACCOUNTLEN); + + /* Parse account ID if provided */ + if (id_str) { + cli_user(cli)->acc_id = strtoul(id_str, NULL, 10); + } + + /* Parse account flags if provided */ + if (flags_str) { + cli_user(cli)->acc_flags = strtoul(flags_str, NULL, 10); + } + + SetAccount(cli); + SetFlag(cli, FLAG_SASL); + + /* Check for +x flag (host hiding) */ + if (extra && strstr(extra, "+x")) { + SetHiddenHost(cli); + } + + MyFree(account_copy); + } + + cli_sasl(cli) = 0; + SetFlag(cli, FLAG_SASL); + + send_reply(cli, RPL_LOGGEDIN, + cli_name(cli), cli_user(cli)->username, + cli_user(cli)->host, cli_user(cli)->account, + cli_user(cli)->account); + send_reply(cli, RPL_SASLSUCCESS); + + /* Increment successful authentication counter */ + sasl_server.auth_success++; + + + } else if (0 == ircd_strncmp(reply, "NO ", 3)) { + /* Authentication failed, send failure message to client */ + send_reply(cli, ERR_SASLFAIL, reply + 3); + cli_sasl(cli) = 0; + + /* Increment failed authentication counter */ + sasl_server.auth_failed++; + + } else if (0 == ircd_strncmp(reply, "SASL ", 5)) { + /* Send the AUTHENTICATE reply to the client */ + sendcmdto_one(&me, CMD_AUTHENTICATE, cli, "%s", reply + 5); + } +} + +/** Generate SASL statistics for /STATS S + * @param[in] sptr Client requesting statistics + * @param[in] sd Stats descriptor (unused) + * @param[in] param Additional parameter (unused) + */ +void sasl_stats(struct Client* sptr, const struct StatDesc* sd, char* param) +{ + if (sasl_server.server && sasl_server.mechanisms) { + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + ":SASL server: %s", sasl_server.server); + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + ":SASL mechanisms: %s", sasl_server.mechanisms); + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + ":SASL successful auths: %lu", sasl_server.auth_success); + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + ":SASL failed auths: %lu", sasl_server.auth_failed); + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + ":SASL available: %s", sasl_available() ? "Yes" : "No"); + } else { + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + ":SASL not configured"); + } +} \ No newline at end of file From 9b3cc99f3af56a3359bcacf9aee05057c4e38e03 Mon Sep 17 00:00:00 2001 From: MrIron Date: Fri, 3 Oct 2025 14:04:36 +0200 Subject: [PATCH 04/13] Added netconf feature. Timer to SASL auth. --- include/client.h | 5 + include/handlers.h | 2 +- include/ircd_config.h | 75 +++++++++ include/ircd_features.h | 1 + include/msg.h | 6 +- include/sasl.h | 5 +- ircd/Makefile.in | 2 + ircd/ircd.c | 3 + ircd/ircd_config.c | 334 ++++++++++++++++++++++++++++++++++++++++ ircd/ircd_features.c | 1 + ircd/m_cap.c | 4 +- ircd/m_config.c | 93 +++++++++++ ircd/m_endburst.c | 1 + ircd/m_sasl.c | 149 ++++++++++++------ ircd/parse.c | 9 +- ircd/s_bsd.c | 7 + ircd/s_serv.c | 5 +- ircd/s_stats.c | 4 + ircd/sasl.c | 120 +++++++-------- 19 files changed, 704 insertions(+), 122 deletions(-) create mode 100644 include/ircd_config.h create mode 100644 ircd/ircd_config.c create mode 100644 ircd/m_config.c diff --git a/include/client.h b/include/client.h index acef7746..5ed61a7f 100644 --- a/include/client.h +++ b/include/client.h @@ -239,6 +239,7 @@ struct Connection struct AuthRequest* con_auth; /**< Auth request for client */ const struct wline* con_wline; /**< WebIRC authorization for client */ uint64_t con_sasl; /**< SASL session cookie */ + struct Timer con_sasl_timer; /**< SASL timeout timer */ }; /** Magic constant to identify valid Connection structures. */ @@ -392,6 +393,8 @@ struct Client { #define cli_sentalong(cli) con_sentalong(cli_connect(cli)) /** Get SASL session cookie for client. */ #define cli_sasl(cli) con_sasl(cli_connect(cli)) +/** Get SASL timeout timer for client. */ +#define cli_sasl_timer(cli) (&con_sasl_timer(cli_connect(cli))) /** Verify that a connection is valid. */ #define con_verify(con) ((con)->con_magic == CONNECTION_MAGIC) @@ -477,6 +480,8 @@ struct Client { #define con_wline(con) ((con)->con_wline) /** Get the SASL session cookie for the connection. */ #define con_sasl(con) ((con)->con_sasl) +/** Get the SASL timeout timer for the connection. */ +#define con_sasl_timer(con) ((con)->con_sasl_timer) #define STAT_CONNECTING 0x001 /**< connecting to another server */ #define STAT_HANDSHAKE 0x002 /**< pass - server sent */ diff --git a/include/handlers.h b/include/handlers.h index 38361d83..0bed5225 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -125,7 +125,7 @@ extern int m_pseudo(struct Client*, struct Client*, int, char*[]); extern int m_quit(struct Client*, struct Client*, int, char*[]); extern int m_registered(struct Client*, struct Client*, int, char*[]); extern int m_sasl(struct Client*, struct Client*, int, char*[]); -extern int ms_sasl(struct Client*, struct Client*, int, char*[]); +extern int ms_config(struct Client*, struct Client*, int, char*[]); extern int m_silence(struct Client*, struct Client*, int, char*[]); extern int m_stats(struct Client*, struct Client*, int, char*[]); extern int m_time(struct Client*, struct Client*, int, char*[]); diff --git a/include/ircd_config.h b/include/ircd_config.h new file mode 100644 index 00000000..6293a388 --- /dev/null +++ b/include/ircd_config.h @@ -0,0 +1,75 @@ +/* + * IRC - Internet Relay Chat, include/ircd_config.h + * Copyright (C) 2025 MrIron + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** @file + * @brief Generic server configuration system declarations. + * @version $Id$ + */ + +#ifndef INCLUDED_ircd_config_h +#define INCLUDED_ircd_config_h + +#include + +struct Client; +struct StatDesc; + +/** Configuration set return values */ +#define CONFIG_REJECTED -1 /**< Rejected - older timestamp */ +#define CONFIG_CREATED 0 /**< New entry created */ +#define CONFIG_TIMESTAMP 1 /**< Timestamp updated, same value */ +#define CONFIG_CHANGED 2 /**< Value actually changed */ + +/** Configuration entry structure */ +struct ConfigEntry { + char *key; /**< Configuration option key */ + char *value; /**< Configuration option value */ + time_t timestamp; /**< Timestamp when this config was set */ + struct ConfigEntry *next; /**< Next configuration entry */ +}; + +/** Configuration change callback function type */ +typedef void (*config_callback_f)(const char *key, const char *old_value, const char *new_value); + +/** Configuration callback structure */ +struct ConfigCallback { + char *key_prefix; /**< Key prefix to match (e.g., "sasl.") */ + config_callback_f callback; /**< Callback function */ + struct ConfigCallback *next; /**< Next callback */ +}; + +/* + * Prototypes + */ + +extern void config_cleanup(void); +extern int config_set(const char *key, const char *value, time_t timestamp); +extern const char *config_get(const char *key); +extern time_t config_get_timestamp(const char *key); +extern void config_remove(const char *key); +extern int config_count(void); +extern void config_register_callback(const char *key_prefix, config_callback_f callback); +extern void config_unregister_callback(const char *key_prefix); +extern void config_burst(struct Client *cptr); +extern void config_stats(struct Client *sptr, const struct StatDesc *sd, char *param); + +#endif /* INCLUDED_ircd_config_h */ \ No newline at end of file diff --git a/include/ircd_features.h b/include/ircd_features.h index e77d08e4..8fb17741 100644 --- a/include/ircd_features.h +++ b/include/ircd_features.h @@ -122,6 +122,7 @@ enum Feature { FEAT_HIS_LINKS, FEAT_HIS_TRACE, FEAT_HIS_STATS_a, + FEAT_HIS_STATS_C, FEAT_HIS_STATS_c, FEAT_HIS_STATS_d, FEAT_HIS_STATS_e, diff --git a/include/msg.h b/include/msg.h index e412f09e..ead6f366 100644 --- a/include/msg.h +++ b/include/msg.h @@ -377,9 +377,13 @@ struct Client; #define CMD_CHGHOST MSG_CHGHOST, TOK_CHGHOST #define MSG_AUTHENTICATE "AUTHENTICATE" -#define TOK_AUTHENTICATE "AU" +#define TOK_AUTHENTICATE "AUTHENTICATE" #define CMD_AUTHENTICATE MSG_AUTHENTICATE, TOK_AUTHENTICATE +#define MSG_CONFIG "CONFIG" +#define TOK_CONFIG "CF" +#define CMD_CONFIG MSG_CONFIG, TOK_CONFIG + /* * Constants */ diff --git a/include/sasl.h b/include/sasl.h index c167a769..66b79497 100644 --- a/include/sasl.h +++ b/include/sasl.h @@ -28,16 +28,15 @@ struct Client; struct StatDesc; /* Public SASL functions */ +extern void sasl_init(void); extern int sasl_available(void); extern const char* sasl_get_server(void); extern const char* sasl_get_mechanisms(void); extern int sasl_mechanism_supported(const char* mechanism); -extern void sasl_update_configuration(time_t timestamp, const char* server, const char* mechanisms); -extern time_t sasl_get_timestamp(void); -extern void sasl_burst(struct Client* cptr); extern void sasl_check_capability(void); extern void sasl_send_xreply(struct Client* sptr, const char* routing, const char* reply); extern struct Client* find_sasl_client(unsigned long cookie); extern void sasl_stats(struct Client* sptr, const struct StatDesc* sd, char* param); +extern void sasl_stop_timeout(struct Client* cptr); #endif /* INCLUDED_sasl_h */ \ No newline at end of file diff --git a/ircd/Makefile.in b/ircd/Makefile.in index 48d0eb34..80db3206 100644 --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -97,6 +97,7 @@ IRCD_SRC = \ hash.c \ ircd.c \ ircd_alloc.c \ + ircd_config.c \ ircd_crypt.c \ ircd_events.c \ ircd_features.c \ @@ -165,6 +166,7 @@ IRCD_SRC = \ m_rping.c \ m_rpong.c \ m_sasl.c \ + m_config.c \ m_server.c \ m_set.c \ m_settime.c \ diff --git a/ircd/ircd.c b/ircd/ircd.c index d643fb09..2c6d5d78 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -33,6 +33,7 @@ #include "ircd_alloc.h" #include "ircd_events.h" #include "ircd_features.h" +#include "ircd_config.h" #include "ircd_log.h" #include "ircd_reply.h" #include "ircd_signal.h" @@ -54,6 +55,7 @@ #include "s_debug.h" #include "s_misc.h" #include "s_stats.h" +#include "sasl.h" #include "send.h" #include "sys.h" #include "uping.h" @@ -698,6 +700,7 @@ int main(int argc, char **argv) { initwhowas(); initmsgtree(); initstats(); + sasl_init(); /* we need this for now, when we're modular this should be removed -- hikari */ diff --git a/ircd/ircd_config.c b/ircd/ircd_config.c new file mode 100644 index 00000000..590bae96 --- /dev/null +++ b/ircd/ircd_config.c @@ -0,0 +1,334 @@ +/* + * IRC - Internet Relay Chat, ircd/ircd_config.c + * Copyright (C) 2025 MrIron + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** @file + * @brief Generic server configuration system implementation. + */ + +#include "config.h" + +#include "ircd_config.h" +#include "client.h" +#include "ircd.h" +#include "ircd_alloc.h" +#include "ircd_reply.h" +#include "ircd_string.h" +#include "msg.h" +#include "numeric.h" +#include "numnicks.h" +#include "s_debug.h" +#include "send.h" + +#include +#include + +/** Head of the configuration list */ +static struct ConfigEntry *config_list = NULL; + +/** Head of the callback list */ +static struct ConfigCallback *callback_list = NULL; + + + +/** Cleanup the configuration system */ +void config_cleanup(void) +{ + struct ConfigEntry *entry = config_list; + struct ConfigEntry *next; + struct ConfigCallback *cb = callback_list; + struct ConfigCallback *cb_next; + + while (entry) { + next = entry->next; + MyFree(entry->key); + MyFree(entry->value); + MyFree(entry); + entry = next; + } + + while (cb) { + cb_next = cb->next; + MyFree(cb->key_prefix); + MyFree(cb); + cb = cb_next; + } + + config_list = NULL; + callback_list = NULL; +} + +/** Find a configuration entry by key + * @param[in] key Configuration key to find + * @return Configuration entry or NULL if not found + */ +static struct ConfigEntry *config_find(const char *key) +{ + struct ConfigEntry *entry; + + assert(key != NULL); + + for (entry = config_list; entry; entry = entry->next) { + if (ircd_strcmp(entry->key, key) == 0) + return entry; + } + + return NULL; +} + +/** Call registered callbacks for a key + * @param[in] key Configuration key that changed + * @param[in] old_value Previous value (NULL if new) + * @param[in] new_value New value + */ +static void config_call_callbacks(const char *key, const char *old_value, const char *new_value) +{ + struct ConfigCallback *cb; + + for (cb = callback_list; cb; cb = cb->next) { + if (ircd_strncmp(key, cb->key_prefix, strlen(cb->key_prefix)) == 0) { + cb->callback(key, old_value, new_value); + } + } +} + +/** Set a configuration option + * @param[in] key Configuration key + * @param[in] value Configuration value + * @param[in] timestamp Timestamp when this config was set + * @return 1 if the value was updated, 0 if it was created, -1 on error + */ +int config_set(const char *key, const char *value, time_t timestamp) +{ + struct ConfigEntry *entry; + char *old_value = NULL; + int result; + + assert(key != NULL); + assert(value != NULL); + + entry = config_find(key); + + if (entry) { + /* Only update if timestamp is newer */ + if (timestamp <= entry->timestamp) + return CONFIG_REJECTED; + + /* Save old value for callbacks */ + DupString(old_value, entry->value); + + /* Check if value actually changed */ + int value_changed = (ircd_strcmp(old_value, value) != 0); + + /* Update existing entry */ + MyFree(entry->value); + DupString(entry->value, value); + entry->timestamp = timestamp; + + result = value_changed ? CONFIG_CHANGED : CONFIG_TIMESTAMP; + } else { + /* Create new entry */ + entry = MyMalloc(sizeof(struct ConfigEntry)); + DupString(entry->key, key); + DupString(entry->value, value); + entry->timestamp = timestamp; + entry->next = config_list; + config_list = entry; + result = CONFIG_CREATED; + } + + Debug((DEBUG_INFO, "Config %s: %s = %s (timestamp: %lu)", + (result == CONFIG_CHANGED) ? "changed" : + (result == CONFIG_TIMESTAMP) ? "timestamp updated" : "set", + key, value, (unsigned long)timestamp)); + + /* Call callbacks */ + config_call_callbacks(key, old_value, value); + + if (old_value) + MyFree(old_value); + + return result; +} + +/** Get a configuration value + * @param[in] key Configuration key + * @return Configuration value or NULL if not found + */ +const char *config_get(const char *key) +{ + struct ConfigEntry *entry; + + assert(key != NULL); + + entry = config_find(key); + return entry ? entry->value : NULL; +} + +/** Get the timestamp of a configuration option + * @param[in] key Configuration key + * @return Timestamp or 0 if not found + */ +time_t config_get_timestamp(const char *key) +{ + struct ConfigEntry *entry; + + assert(key != NULL); + + entry = config_find(key); + return entry ? entry->timestamp : 0; +} + +/** Remove a configuration option + * @param[in] key Configuration key to remove + */ +void config_remove(const char *key) +{ + struct ConfigEntry *entry, *prev = NULL; + + assert(key != NULL); + + for (entry = config_list; entry; prev = entry, entry = entry->next) { + if (ircd_strcmp(entry->key, key) == 0) { + if (prev) + prev->next = entry->next; + else + config_list = entry->next; + + MyFree(entry->key); + MyFree(entry->value); + MyFree(entry); + + Debug((DEBUG_INFO, "Config removed: %s", key)); + return; + } + } +} + +/** Count the number of configuration entries + * @return Number of configuration entries + */ +int config_count(void) +{ + struct ConfigEntry *entry; + int count = 0; + + for (entry = config_list; entry; entry = entry->next) + count++; + + return count; +} + +/** Register a callback for configuration changes + * @param[in] key_prefix Key prefix to match (e.g., "sasl.") + * @param[in] callback Callback function to call + */ +void config_register_callback(const char *key_prefix, config_callback_f callback) +{ + struct ConfigCallback *cb; + + assert(key_prefix != NULL); + assert(callback != NULL); + + /* Check if callback already exists */ + for (cb = callback_list; cb; cb = cb->next) { + if (ircd_strcmp(cb->key_prefix, key_prefix) == 0) { + cb->callback = callback; + return; + } + } + + /* Create new callback */ + cb = MyMalloc(sizeof(struct ConfigCallback)); + DupString(cb->key_prefix, key_prefix); + cb->callback = callback; + cb->next = callback_list; + callback_list = cb; + + Debug((DEBUG_INFO, "Config callback registered for prefix: %s", key_prefix)); +} + +/** Unregister a callback for configuration changes + * @param[in] key_prefix Key prefix that was registered + */ +void config_unregister_callback(const char *key_prefix) +{ + struct ConfigCallback *cb, *prev = NULL; + + assert(key_prefix != NULL); + + for (cb = callback_list; cb; prev = cb, cb = cb->next) { + if (ircd_strcmp(cb->key_prefix, key_prefix) == 0) { + if (prev) + prev->next = cb->next; + else + callback_list = cb->next; + + MyFree(cb->key_prefix); + MyFree(cb); + + Debug((DEBUG_INFO, "Config callback unregistered for prefix: %s", key_prefix)); + return; + } + } +} + +/** Burst all configuration entries to a newly connected server + * @param[in] cptr Server to send CF messages to + */ +void config_burst(struct Client *cptr) +{ + struct ConfigEntry *entry; + + for (entry = config_list; entry; entry = entry->next) { + sendcmdto_one(&me, CMD_CONFIG, cptr, "%Tu %s %s", + entry->timestamp, entry->key, entry->value); + } + + Debug((DEBUG_INFO, "Config burst: %d entries sent to %s", + config_count(), cli_name(cptr))); +} + +/** Generate configuration statistics for /STATS C + * @param[in] sptr Client requesting statistics + * @param[in] sd Stats descriptor (unused) + * @param[in] param Additional parameter (unused) + */ +void config_stats(struct Client *sptr, const struct StatDesc *sd, char *param) +{ + struct ConfigEntry *entry; + int count = 0; + + for (entry = config_list; entry; entry = entry->next) { + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + "%Tu %s :%s", + entry->timestamp, entry->key, entry->value); + count++; + } + + if (count == 0) { + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + ":No configuration entries"); + } else { + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + ":Total configuration entries: %d", count); + } +} \ No newline at end of file diff --git a/ircd/ircd_features.c b/ircd/ircd_features.c index 15f7025a..ad0ae8e4 100644 --- a/ircd/ircd_features.c +++ b/ircd/ircd_features.c @@ -387,6 +387,7 @@ static struct FeatureDesc { F_B(HIS_LINKS, 0, 1, 0), F_B(HIS_TRACE, 0, 1, 0), F_B(HIS_STATS_a, 0, 1, 0), + F_B(HIS_STATS_C, 0, 1, 0), F_B(HIS_STATS_c, 0, 1, 0), F_B(HIS_STATS_d, 0, 1, 0), F_B(HIS_STATS_e, 0, 1, 0), diff --git a/ircd/m_cap.c b/ircd/m_cap.c index 593f3253..32f6c8e7 100644 --- a/ircd/m_cap.c +++ b/ircd/m_cap.c @@ -399,9 +399,9 @@ void cap_new(enum Capab cap) /* Send CAP NEW message */ if (cap_value && *cap_value && HasFlag(acptr, FLAG_CAP302)) { - sendcmdto_one(&me, CMD_CAP, acptr, "%C NEW :%s=%s", acptr, cap_name, cap_value); + sendcmdto_one(&me, CMD_CAP, acptr, "%C NEW %s=%s", acptr, cap_name, cap_value); } else { - sendcmdto_one(&me, CMD_CAP, acptr, "%C NEW :%s", acptr, cap_name); + sendcmdto_one(&me, CMD_CAP, acptr, "%C NEW %s", acptr, cap_name); } } } diff --git a/ircd/m_config.c b/ircd/m_config.c new file mode 100644 index 00000000..91e749a5 --- /dev/null +++ b/ircd/m_config.c @@ -0,0 +1,93 @@ +/* + * IRC - Internet Relay Chat, ircd/m_config.c + * Copyright (C) 2025 MrIron + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** @file + * @brief Handler for the CONFIG command. + */ + +#include "config.h" + +#include "client.h" +#include "ircd.h" +#include "ircd_config.h" +#include "ircd_reply.h" +#include "ircd_string.h" +#include "msg.h" +#include "numeric.h" +#include "numnicks.h" +#include "send.h" +#include "s_debug.h" + +#include + +/** Handler for server CONFIG messages + * @param[in] cptr Local client that sent us the message + * @param[in] sptr Original source of the message + * @param[in] parc Number of parameters + * @param[in] parv Parameter vector (source CF timestamp key value) + * @return 0 on success + */ +int ms_config(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) +{ + time_t timestamp; + const char *key, *value; + const char *old_value; + int result; + + if (parc < 4) + return need_more_params(sptr, "CF"); + + timestamp = atol(parv[1]); + key = parv[2]; + value = parv[3]; + + /* Get the old value for comparison */ + old_value = config_get(key); + + /* Try to set the configuration */ + result = config_set(key, value, timestamp); + + if (result != CONFIG_REJECTED) { + /* Configuration was set or updated, propagate to other servers */ + sendcmdto_serv_butone(sptr, CMD_CONFIG, cptr, "%Tu %s :%s", + timestamp, key, value); + + /* Send notification to operators based on what actually happened */ + if (result == CONFIG_CREATED) { + /* New configuration option */ + sendto_opmask_butone(0, SNO_NETWORK, + "Server configuration set: %s = %s", + key, value); + } else if (result == CONFIG_CHANGED) { + /* Value actually changed */ + sendto_opmask_butone(0, SNO_NETWORK, + "Server configuration updated: %s = %s (was: %s)", + key, value, old_value ? old_value : "(unset)"); + } + /* CONFIG_TIMESTAMP (timestamp only update) - no notification */ + + Debug((DEBUG_INFO, "CONFIG: %s set %s = %s (timestamp: %Tu)", + cli_name(sptr), key, value, timestamp)); + } + + return 0; +} diff --git a/ircd/m_endburst.c b/ircd/m_endburst.c index 15fd6e4b..241b6790 100644 --- a/ircd/m_endburst.c +++ b/ircd/m_endburst.c @@ -88,6 +88,7 @@ #include "ircd_log.h" #include "ircd_reply.h" #include "ircd_string.h" +#include "sasl.h" #include "msg.h" #include "numeric.h" #include "numnicks.h" diff --git a/ircd/m_sasl.c b/ircd/m_sasl.c index a822fe19..d937ae40 100644 --- a/ircd/m_sasl.c +++ b/ircd/m_sasl.c @@ -81,6 +81,9 @@ #include "client.h" #include "ircd.h" +#include "ircd_config.h" +#include "ircd_events.h" +#include "ircd_log.h" #include "ircd_reply.h" #include "ircd_string.h" #include "msg.h" @@ -88,9 +91,93 @@ #include "numnicks.h" #include "sasl.h" #include "send.h" +#include "s_debug.h" #include +/** SASL timeout callback - called when a SASL session times out + * @param[in] ev Timer event (contains client pointer in timer data) + */ +static void sasl_timeout_callback(struct Event* ev) +{ + struct Client* cptr; + + assert(0 != ev_timer(ev)); + assert(0 != t_data(ev_timer(ev))); + + if (ev_type(ev) == ET_EXPIRE) { + cptr = (struct Client*) t_data(ev_timer(ev)); + + /* Verify the client is still valid */ + if (!cptr || cli_magic(cptr) != CLIENT_MAGIC || !MyConnect(cptr)) + return; + + /* Verify the client still has an active SASL session */ + if (!cli_sasl(cptr)) + return; + + Debug((DEBUG_INFO, "SASL timeout for client %s (cookie: %lu)", + cli_name(cptr), cli_sasl(cptr))); + + /* Send timeout error to client */ + send_reply(cptr, ERR_SASLFAIL, "Authentication timed out"); + + /* Clear SASL session */ + cli_sasl(cptr) = 0; + } +}/** Start the SASL timeout timer for a client + * @param[in] cptr Client to set timeout for + */ +static void sasl_start_timeout(struct Client* cptr) +{ + struct Timer* timer; + const char* timeout_str; + int timeout_seconds = 60; /* Default 1 minute */ + + assert(cptr != NULL); + assert(MyConnect(cptr)); + assert(cli_sasl(cptr) != 0); /* Should have active SASL session */ + + /* Get configured timeout */ + timeout_str = config_get("sasl.timeout"); + if (timeout_str) { + timeout_seconds = atoi(timeout_str); + if (timeout_seconds <= 0) + timeout_seconds = 60; + } + + timer = cli_sasl_timer(cptr); + + /* Timer should not already be active */ + assert(!t_active(timer)); + + /* Start timer */ + timer_add(timer_init(timer), sasl_timeout_callback, (void*) cptr, + TT_RELATIVE, timeout_seconds); + + Debug((DEBUG_INFO, "SASL timeout started for client %s (%d seconds)", + cli_name(cptr), timeout_seconds)); +} + +/** Stop the SASL timeout timer for a client + * @param[in] cptr Client to stop timeout for + */ +void sasl_stop_timeout(struct Client* cptr) +{ + struct Timer* timer; + + assert(cptr != NULL); + assert(MyConnect(cptr)); + + timer = cli_sasl_timer(cptr); + + /* Only delete if timer exists and is active */ + if (t_active(timer)) { + timer_del(timer); + Debug((DEBUG_INFO, "SASL timeout stopped for client %s", cli_name(cptr))); + } +} + int m_sasl(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client* acptr; @@ -113,8 +200,12 @@ int m_sasl(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return send_reply(cptr, ERR_SASLTOOLONG); if (strcmp(parv[1], "*") == 0) { + /* SASL abort - stop timeout and clear session */ + if (cli_sasl(cptr)) { + sasl_stop_timeout(cptr); + cli_sasl(cptr) = 0; + } send_reply(cptr, ERR_SASLABORTED); - cli_sasl(cptr) = 0; return 0; } @@ -124,9 +215,16 @@ int m_sasl(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return send_reply(cptr, RPL_SASLMECHS, sasl_get_mechanisms()); cli_sasl(cptr) = ++routing_ticker; + + Debug((DEBUG_INFO, "SASL session started for %s (cookie: %lu)", + cli_name(cptr), cli_sasl(cptr))); - /* Is the user already registered? We then send the NumNick. */ + /* Start timeout for new session */ + sasl_start_timeout(cptr); + + /* Send the initial SASL message to the authentication server */ if (IsUser(cptr)) { + /* Is the user already registered? We then send the NumNick. */ sendcmdto_one(&me, CMD_XQUERY, acptr, "%C sasl:%lu :SASL %s%s %s", acptr, cli_sasl(cptr), NumNick(cptr), parv[1]); } else { @@ -137,6 +235,10 @@ int m_sasl(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) parv[1]); } } else { + /* Continuation message - cli_sasl(cptr) should be non-zero */ + assert(cli_sasl(cptr) != 0); + + /* Send continuation SASL message (timer keeps running) */ sendcmdto_one(&me, CMD_XQUERY, acptr, "%C sasl:%lu :SASL %s", acptr, cli_sasl(cptr), parv[1]); } @@ -144,46 +246,3 @@ int m_sasl(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return 0; } -/** Handler for configuring the SASL authentication layer on the network - * @param[in] cptr Local client that sent us the message - * @param[in] sptr Original source of the message - * @param[in] parc Number of parameters - * @param[in] parv Parameter vector - * @return 0 on success - */ -int ms_sasl(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) -{ - time_t timestamp; - struct Client* acptr; - - if (parc < 2) - return need_more_params(sptr, "AU"); - - /* Check if this is a configuration message */ - if (parv[1][0] == '=') { - /* Format: AU = */ - if (parc < 5) - return need_more_params(sptr, "AU"); - - timestamp = atoi(parv[2]); - if (timestamp > sasl_get_timestamp() || !sasl_get_server()) { - const char* old_server = sasl_get_server(); - const char* old_mechanisms = sasl_get_mechanisms(); - - sasl_update_configuration(timestamp, parv[3], parv[4]); - sendcmdto_serv_butone(sptr, CMD_AUTHENTICATE, cptr, "= %s %s %s", - parv[2], parv[3], parv[4]); - - /* Only send opmask if there was actually a change */ - if (!old_server || !old_mechanisms || - ircd_strcmp(old_server, parv[3]) != 0 || - ircd_strcmp(old_mechanisms, parv[4]) != 0) { - sendto_opmask_butone(0, SNO_NETWORK, - "SASL authentication layer is %s accepting %s", - parv[3], parv[4]); - } - } - } - - return 0; -} \ No newline at end of file diff --git a/ircd/parse.c b/ircd/parse.c index 061792c4..06efddc8 100644 --- a/ircd/parse.c +++ b/ircd/parse.c @@ -663,7 +663,14 @@ struct Message msgtab[] = { TOK_AUTHENTICATE, 0, MAXPARA, 0, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ - { m_sasl, m_sasl, ms_sasl, m_sasl, m_ignore } + { m_sasl, m_sasl, m_ignore, m_sasl, m_ignore } + }, + { + MSG_CONFIG, + TOK_CONFIG, + 0, MAXPARA, 0, 0, NULL, + /* UNREG, CLIENT, SERVER, OPER, SERVICE */ + { m_ignore, m_ignore, ms_config, m_ignore, m_ignore } }, { 0 } }; diff --git a/ircd/s_bsd.c b/ircd/s_bsd.c index 9bfb8760..c33556d1 100644 --- a/ircd/s_bsd.c +++ b/ircd/s_bsd.c @@ -30,6 +30,7 @@ #include "class.h" #include "hash.h" #include "ircd_alloc.h" +#include "ircd_events.h" #include "ircd_log.h" #include "ircd_features.h" #include "ircd_osdep.h" @@ -428,6 +429,12 @@ void close_connection(struct Client *cptr) det_confs_butmask(cptr, 0); + /* Clean up SASL timer if it exists */ + if (cli_sasl_timer(cptr) && t_active(cli_sasl_timer(cptr))) { + timer_del(cli_sasl_timer(cptr)); + memset(cli_sasl_timer(cptr), 0, sizeof(struct Timer)); + } + if (cli_listener(cptr)) { release_listener(cli_listener(cptr)); cli_listener(cptr) = 0; diff --git a/ircd/s_serv.c b/ircd/s_serv.c index 662f6302..820830ed 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -34,6 +34,7 @@ #include "hash.h" #include "ircd.h" #include "ircd_alloc.h" +#include "ircd_config.h" #include "ircd_log.h" #include "ircd_reply.h" #include "ircd_string.h" @@ -198,8 +199,8 @@ int server_estab(struct Client *cptr, struct ConfItem *aconf) gline_burst(cptr); jupe_burst(cptr); - /* Burst SASL configuration. */ - sasl_burst(cptr); + /* Burst server configuration. */ + config_burst(cptr); /* * Pass on my client information to the new server diff --git a/ircd/s_stats.c b/ircd/s_stats.c index 4f5af674..960bda4d 100644 --- a/ircd/s_stats.c +++ b/ircd/s_stats.c @@ -27,6 +27,7 @@ #include "hash.h" #include "ircd.h" #include "ircd_chattr.h" +#include "ircd_config.h" #include "ircd_events.h" #include "ircd_features.h" #include "ircd_crypt.h" @@ -662,6 +663,9 @@ struct StatDesc statsinfo[] = { { ' ', "iauthconf", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_IAUTH, report_iauth_conf, 0, "IAuth configuration." }, + { ' ', "netconf", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_C, + config_stats, 0, + "Network configuration entries." }, { '*', "help", STAT_FLAG_CASESENS, FEAT_LAST_F, stats_help, 0, "Send help for stats." }, diff --git a/ircd/sasl.c b/ircd/sasl.c index 055360e0..f73ad955 100644 --- a/ircd/sasl.c +++ b/ircd/sasl.c @@ -30,6 +30,8 @@ #include "client.h" #include "ircd.h" #include "ircd_alloc.h" +#include "ircd_config.h" +#include "ircd_events.h" #include "ircd_string.h" #include "ircd_reply.h" #include "send.h" @@ -42,26 +44,24 @@ #include -/** SASL server information */ -struct SaslServer { - time_t timestamp; /**< Timestamp of the AU configuration */ - char *server; /**< Server name providing SASL */ - char *mechanisms; /**< Comma-delimited list of supported mechanisms */ +/** SASL statistics */ +struct SaslStats { unsigned long auth_success; /**< Number of successful authentications */ unsigned long auth_failed; /**< Number of failed authentications */ }; -/** Global SASL server info - only one allowed */ -static struct SaslServer sasl_server = { 0, NULL, NULL, 0, 0 }; +/** Global SASL statistics */ +static struct SaslStats sasl_statistics = { 0, 0 }; /** Check if SASL is available * @return 1 if SASL server is configured, 0 otherwise */ int sasl_available(void) { - if (sasl_server.server == NULL - || sasl_server.mechanisms == NULL - || !find_match_server((char*)sasl_get_server())) + const char* server = config_get("sasl.server"); + const char* mechanisms = config_get("sasl.mechanisms"); + + if (!server || !mechanisms || !find_match_server((char*)server)) return 0; return 1; @@ -72,7 +72,7 @@ int sasl_available(void) */ const char* sasl_get_server(void) { - return sasl_server.server; + return config_get("sasl.server"); } /** Get the current SASL mechanisms @@ -80,7 +80,7 @@ const char* sasl_get_server(void) */ const char* sasl_get_mechanisms(void) { - return sasl_server.mechanisms; + return config_get("sasl.mechanisms"); } /** Check if a mechanism exists in a mechanism list @@ -125,66 +125,41 @@ static int mechanism_in_list(const char* mechanism, const char* mechanism_list) */ int sasl_mechanism_supported(const char* mechanism) { - return mechanism_in_list(mechanism, sasl_server.mechanisms); + return mechanism_in_list(mechanism, config_get("sasl.mechanisms")); } -/** Update SASL configuration - * @param[in] timestamp Timestamp from AU message - * @param[in] server Server name - * @param[in] mechanisms Comma-delimited mechanism list - */ -void sasl_update_configuration(time_t timestamp, const char* server, const char* mechanisms) -{ - /* Free old data */ - if (sasl_server.server) { - MyFree(sasl_server.server); - sasl_server.server = NULL; - } - if (sasl_server.mechanisms) { - MyFree(sasl_server.mechanisms); - sasl_server.mechanisms = NULL; - } - - /* Set new data */ - sasl_server.timestamp = timestamp; - DupString(sasl_server.server, server); - DupString(sasl_server.mechanisms, mechanisms); - - /* Update capability information */ - cap_set_value(E_CAP_SASL, sasl_server.mechanisms); - - /* Check if SASL capability availability changed */ - sasl_check_capability(); -} - -/** Get SASL server timestamp - * @return Timestamp of current SASL server info +/** Check and update SASL capability availability + * This function should be called when events occur that might change + * SASL availability (netjoin/netsplit, config changes) */ -time_t sasl_get_timestamp(void) +void sasl_check_capability(void) { - return sasl_server.timestamp; + cap_update_availability(E_CAP_SASL, sasl_available()); } -/** Burst SASL server information to a newly connected server - * @param[in] cptr Server to send AU message to +/** Config change callback for SASL-related configuration + * @param[in] key Configuration key that changed + * @param[in] old_value Old value (NULL if new key) + * @param[in] new_value New value */ -void sasl_burst(struct Client* cptr) +static void sasl_config_callback(const char *key, const char *old_value, const char *new_value) { - if (sasl_server.server && sasl_server.mechanisms) { - sendcmdto_one(&me, CMD_AUTHENTICATE, cptr, "= %Tu %s %s", - sasl_server.timestamp, - sasl_server.server, - sasl_server.mechanisms); + Debug((DEBUG_INFO, "SASL config changed: %s = %s (was: %s)", + key, new_value, old_value ? old_value : "(unset)")); + + /* Update SASL capability value if mechanisms changed */ + if (ircd_strcmp(key, "sasl.mechanisms") == 0) { + cap_set_value(E_CAP_SASL, new_value); } + + /* Update SASL capability availability */ + sasl_check_capability(); } -/** Check and update SASL capability availability - * This function should be called when events occur that might change - * SASL availability (netjoin/netsplit, AU messages) - */ -void sasl_check_capability(void) +/** Initialize SASL subsystem and register config callbacks */ +void sasl_init(void) { - cap_update_availability(E_CAP_SASL, sasl_available()); + config_register_callback("sasl.", sasl_config_callback); } /** Find a client by their SASL session cookie @@ -280,6 +255,8 @@ void sasl_send_xreply(struct Client* sptr, const char* routing, const char* repl MyFree(account_copy); } + /* Stop SASL timeout timer and clear session */ + sasl_stop_timeout(cli); cli_sasl(cli) = 0; SetFlag(cli, FLAG_SASL); @@ -290,16 +267,19 @@ void sasl_send_xreply(struct Client* sptr, const char* routing, const char* repl send_reply(cli, RPL_SASLSUCCESS); /* Increment successful authentication counter */ - sasl_server.auth_success++; + sasl_statistics.auth_success++; } else if (0 == ircd_strncmp(reply, "NO ", 3)) { /* Authentication failed, send failure message to client */ send_reply(cli, ERR_SASLFAIL, reply + 3); + + /* Stop SASL timeout timer and clear session */ + sasl_stop_timeout(cli); cli_sasl(cli) = 0; /* Increment failed authentication counter */ - sasl_server.auth_failed++; + sasl_statistics.auth_failed++; } else if (0 == ircd_strncmp(reply, "SASL ", 5)) { /* Send the AUTHENTICATE reply to the client */ @@ -314,15 +294,21 @@ void sasl_send_xreply(struct Client* sptr, const char* routing, const char* repl */ void sasl_stats(struct Client* sptr, const struct StatDesc* sd, char* param) { - if (sasl_server.server && sasl_server.mechanisms) { + const char* server = config_get("sasl.server"); + const char* mechanisms = config_get("sasl.mechanisms"); + const char* timeout = config_get("sasl.timeout"); + + if (server && mechanisms) { + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + ":SASL server: %s", server); send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, - ":SASL server: %s", sasl_server.server); + ":SASL mechanisms: %s", mechanisms); send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, - ":SASL mechanisms: %s", sasl_server.mechanisms); + ":SASL timeout: %s", timeout); send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, - ":SASL successful auths: %lu", sasl_server.auth_success); + ":SASL successful auths: %lu", sasl_statistics.auth_success); send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, - ":SASL failed auths: %lu", sasl_server.auth_failed); + ":SASL failed auths: %lu", sasl_statistics.auth_failed); send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, ":SASL available: %s", sasl_available() ? "Yes" : "No"); } else { From 0d9e2936e781cbcc482c67ae08efcb8161c6089c Mon Sep 17 00:00:00 2001 From: MrIron Date: Fri, 10 Oct 2025 15:45:19 +0200 Subject: [PATCH 05/13] Only send RPL_LOGGEDIN after completion of registration. --- ircd/s_auth.c | 6 ++++++ ircd/sasl.c | 28 ++++++++++++++++------------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/ircd/s_auth.c b/ircd/s_auth.c index ce038181..473ef46f 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -564,6 +564,12 @@ static int check_auth_finished(struct AuthRequest *auth, int bitclr) if (res == 0) { + if (HasFlag(auth->client, FLAG_SASL)) { + send_reply(auth->client, RPL_LOGGEDIN, + cli_name(auth->client), cli_username(auth->client), + cli_user(auth->client)->host, cli_user(auth->client)->account, + cli_user(auth->client)->account); + } memset(cli_passwd(cptr), 0, sizeof(cli_passwd(cptr))); res = register_user(cptr, cptr); } diff --git a/ircd/sasl.c b/ircd/sasl.c index f73ad955..a45a1b69 100644 --- a/ircd/sasl.c +++ b/ircd/sasl.c @@ -219,7 +219,11 @@ void sasl_send_xreply(struct Client* sptr, const char* routing, const char* repl const char *account_info = reply + 3; /* Skip "OK " */ char *account_copy, *username, *id_str, *flags_str, *extra; - + + /** + * We only parse this information if the user is not yet registered (i.e. SASL authentication during auth). + * If this is a SASL authentication after registration, the username will be set by the service using AC. + */ if (!IsUser(cli)) { /* Parse account information: username:id:flags */ DupString(account_copy, account_info); @@ -245,31 +249,31 @@ void sasl_send_xreply(struct Client* sptr, const char* routing, const char* repl } SetAccount(cli); - SetFlag(cli, FLAG_SASL); /* Check for +x flag (host hiding) */ - if (extra && strstr(extra, "+x")) { + if (extra && strstr(extra, "+x") && feature_bool(FEAT_HOST_HIDING)) { SetHiddenHost(cli); } MyFree(account_copy); + + /** + * For already registered users, we send RPL_LOGGEDIN. For non-registered users, + * we send RPL_LOGGEDIN in check_auth_finished(). + */ + } else { + send_reply(cli, RPL_LOGGEDIN, + cli_name(cli), cli_user(cli)->username, + cli_user(cli)->host, cli_user(cli)->account, + cli_user(cli)->account); } - /* Stop SASL timeout timer and clear session */ sasl_stop_timeout(cli); cli_sasl(cli) = 0; SetFlag(cli, FLAG_SASL); - send_reply(cli, RPL_LOGGEDIN, - cli_name(cli), cli_user(cli)->username, - cli_user(cli)->host, cli_user(cli)->account, - cli_user(cli)->account); send_reply(cli, RPL_SASLSUCCESS); - - /* Increment successful authentication counter */ sasl_statistics.auth_success++; - - } else if (0 == ircd_strncmp(reply, "NO ", 3)) { /* Authentication failed, send failure message to client */ send_reply(cli, ERR_SASLFAIL, reply + 3); From c15efe117367ada8d7e34e65849e2c3820ff7f42 Mon Sep 17 00:00:00 2001 From: MrIron Date: Fri, 17 Oct 2025 23:06:21 +0200 Subject: [PATCH 06/13] Network configuration feature will allow services to set network-wide options --- doc/example.conf | 1 + include/handlers.h | 1 + include/ircd_features.h | 5 +- include/ircd_netconf.h | 66 +++ include/msg.h | 4 + ircd/Makefile.in | 1189 ++++++++++++++++++++------------------- ircd/ircd_features.c | 5 +- ircd/ircd_netconf.c | 265 +++++++++ ircd/m_config.c | 94 ++++ ircd/parse.c | 7 + ircd/s_serv.c | 4 + ircd/s_stats.c | 6 +- ircd/test/Makefile.in | 6 +- 13 files changed, 1079 insertions(+), 574 deletions(-) create mode 100644 include/ircd_netconf.h create mode 100644 ircd/ircd_netconf.c create mode 100644 ircd/m_config.c diff --git a/doc/example.conf b/doc/example.conf index 7d881228..ac61e434 100644 --- a/doc/example.conf +++ b/doc/example.conf @@ -933,6 +933,7 @@ features # "HIS_TRACE" = "TRUE"; # "HIS_STATS_a" = "TRUE"; # "HIS_STATS_c" = "TRUE"; +# "HIS_STATS_C" = "TRUE"; # "HIS_STATS_d" = "TRUE"; # "HIS_STATS_e" = "TRUE"; # "HIS_STATS_f" = "TRUE"; diff --git a/include/handlers.h b/include/handlers.h index f8bc6073..d7eea755 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -89,6 +89,7 @@ struct Client; extern int m_admin(struct Client*, struct Client*, int, char*[]); extern int m_away(struct Client*, struct Client*, int, char*[]); extern int m_cap(struct Client*, struct Client*, int, char*[]); +extern int ms_config(struct Client*, struct Client*, int, char*[]); extern int m_cnotice(struct Client*, struct Client*, int, char*[]); extern int m_cprivmsg(struct Client*, struct Client*, int, char*[]); extern int m_gline(struct Client*, struct Client*, int, char*[]); diff --git a/include/ircd_features.h b/include/ircd_features.h index 10167947..3f6bc140 100644 --- a/include/ircd_features.h +++ b/include/ircd_features.h @@ -122,6 +122,7 @@ enum Feature { FEAT_HIS_TRACE, FEAT_HIS_STATS_a, FEAT_HIS_STATS_c, + FEAT_HIS_STATS_C, FEAT_HIS_STATS_d, FEAT_HIS_STATS_e, FEAT_HIS_STATS_f, @@ -132,13 +133,13 @@ enum Feature { FEAT_HIS_STATS_k, FEAT_HIS_STATS_l, FEAT_HIS_STATS_L, - FEAT_HIS_STATS_M, FEAT_HIS_STATS_m, + FEAT_HIS_STATS_M, FEAT_HIS_STATS_o, FEAT_HIS_STATS_p, FEAT_HIS_STATS_q, - FEAT_HIS_STATS_R, FEAT_HIS_STATS_r, + FEAT_HIS_STATS_R, FEAT_HIS_STATS_t, FEAT_HIS_STATS_T, FEAT_HIS_STATS_u, diff --git a/include/ircd_netconf.h b/include/ircd_netconf.h new file mode 100644 index 00000000..7ea59d3c --- /dev/null +++ b/include/ircd_netconf.h @@ -0,0 +1,66 @@ +/* + * IRC - Internet Relay Chat, include/ircd_netconf.h + * Copyright (C) 2025 MrIron + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef INCLUDED_ircd_netconf_h +#define INCLUDED_ircd_netconf_h + +#include + +struct Client; +struct StatDesc; + +/** Configuration set return values */ +#define CONFIG_REJECTED -1 /**< Rejected - older timestamp */ +#define CONFIG_CREATED 0 /**< New entry created */ +#define CONFIG_TIMESTAMP 1 /**< Timestamp updated, same value */ +#define CONFIG_CHANGED 2 /**< Value actually changed */ + +/** Configuration entry structure */ +struct ConfigEntry { + char *key; /**< Configuration option key */ + char *value; /**< Configuration option value */ + time_t timestamp; /**< Timestamp when this config was set */ + struct ConfigEntry *next; /**< Next configuration entry */ +}; + +/** Configuration change callback function type */ +typedef void (*config_callback_f)(const char *key, const char *old_value, const char *new_value); + +/** Configuration callback structure */ +struct ConfigCallback { + char *key_prefix; /**< Key prefix to match (e.g., "sasl.") */ + config_callback_f callback; /**< Callback function */ + struct ConfigCallback *next; /**< Next callback */ +}; + +/* + * Prototypes + */ + +extern int config_set(const char *key, const char *value, time_t timestamp); +extern const char *config_get(const char *key); +extern void config_register_callback(const char *key_prefix, config_callback_f callback); +extern void config_unregister_callback(const char *key_prefix); +extern void config_burst(struct Client *cptr); +extern void config_stats(struct Client *sptr, const struct StatDesc *sd, char *param); + +#endif /* INCLUDED_ircd_config_h */ \ No newline at end of file diff --git a/include/msg.h b/include/msg.h index 2fba1e79..c56c31a3 100644 --- a/include/msg.h +++ b/include/msg.h @@ -376,6 +376,10 @@ struct Client; #define TOK_CHGHOST "CHGHOST" #define CMD_CHGHOST MSG_CHGHOST, TOK_CHGHOST +#define MSG_CONFIG "CONFIG" +#define TOK_CONFIG "CF" +#define CMD_CONFIG MSG_CONFIG, TOK_CONFIG + /* * Constants */ diff --git a/ircd/Makefile.in b/ircd/Makefile.in index 432c66e2..fa45a4d0 100644 --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -102,6 +102,7 @@ IRCD_SRC = \ ircd_features.c \ ircd_lexer.c \ ircd_log.c \ + ircd_netconf.c \ ircd_relay.c \ ircd_reply.c \ ircd_res.c \ @@ -120,6 +121,7 @@ IRCD_SRC = \ m_cap.c \ m_clearmode.c \ m_close.c \ + m_config.c \ m_connect.c \ m_cprivmsg.c \ m_create.c \ @@ -354,85 +356,92 @@ IPcheck.o: IPcheck.c ../config.h ../include/IPcheck.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/capab.h \ - ../include/ircd.h ../include/struct.h ../include/match.h \ - ../include/msg.h ../include/ircd_alloc.h ../include/ircd_events.h \ - ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/res.h \ - ../include/s_debug.h ../include/s_user.h ../include/send.h + ../include/ircd_features.h ../include/ircd.h ../include/struct.h \ + ../include/match.h ../include/msg.h ../include/ircd_alloc.h \ + ../include/ircd_events.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/res.h ../include/s_debug.h ../include/s_user.h \ + ../include/send.h channel.o: channel.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/destruct_event.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h ../include/ircd_defs.h \ - ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_snprintf.h ../include/ircd_string.h ../include/list.h \ - ../include/match.h ../include/msg.h ../include/msgq.h \ - ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ - ../include/ircd_features.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/client.h ../include/s_debug.h ../include/s_misc.h \ - ../include/s_user.h ../include/send.h ../include/struct.h \ - ../include/sys.h ../include/whowas.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/destruct_event.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_chattr.h \ + ../include/ircd_defs.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/ircd_string.h ../include/list.h ../include/match.h \ + ../include/msg.h ../include/msgq.h ../include/numeric.h \ + ../include/numnicks.h ../include/querycmds.h ../include/s_bsd.h \ + ../include/s_conf.h ../include/client.h ../include/s_debug.h \ + ../include/s_misc.h ../include/s_user.h ../include/send.h \ + ../include/struct.h ../include/sys.h ../include/whowas.h class.o: class.c ../config.h ../include/class.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/client.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/list.h ../include/numeric.h \ - ../include/s_conf.h ../include/s_debug.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/client.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ + ../include/numeric.h ../include/s_conf.h ../include/s_debug.h \ + ../include/send.h client.o: client.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/class.h ../include/client.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/list.h ../include/msgq.h \ - ../include/numeric.h ../include/s_conf.h ../include/s_debug.h \ - ../include/send.h ../include/struct.h + ../include/ircd_features.h ../include/class.h ../include/client.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/list.h \ + ../include/msgq.h ../include/numeric.h ../include/s_conf.h \ + ../include/s_debug.h ../include/send.h ../include/struct.h crule.o: crule.c ../config.h ../include/crule.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_chattr.h \ ../include/ircd_string.h ../include/match.h ../include/s_bsd.h \ ../include/s_debug.h ../include/struct.h dbuf.o: dbuf.c ../config.h ../include/dbuf.h ../include/ircd_alloc.h \ ../include/ircd_chattr.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/send.h ../include/sys.h + ../include/ircd_log.h ../include/send.h ../include/client.h \ + ../include/ircd_defs.h ../include/msgq.h ../include/ircd_events.h \ + ../include/ircd_handler.h ../include/res.h ../include/capab.h \ + ../include/ircd_features.h ../include/sys.h destruct_event.o: destruct_event.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/s_debug.h \ ../include/ircd_alloc.h ../include/ircd.h ../include/struct.h \ ../include/ircd_events.h ../include/ircd_log.h ../include/send.h \ - ../include/msg.h ../include/ircd_handler.h + ../include/client.h ../include/dbuf.h ../include/msgq.h \ + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/msg.h fileio.o: fileio.c ../config.h ../include/fileio.h \ ../include/ircd_alloc.h ../include/ircd_log.h gline.o: gline.c ../config.h ../include/gline.h ../include/res.h \ ../include/channel.h ../include/ircd_defs.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_snprintf.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ - ../include/numeric.h ../include/s_bsd.h ../include/s_debug.h \ - ../include/s_misc.h ../include/s_stats.h ../include/send.h \ - ../include/struct.h ../include/sys.h ../include/msg.h \ - ../include/numnicks.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_snprintf.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/match.h ../include/numeric.h \ + ../include/s_bsd.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_stats.h ../include/send.h ../include/struct.h \ + ../include/sys.h ../include/msg.h ../include/numnicks.h hash.o: hash.c ../config.h ../include/hash.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/channel.h ../include/ircd_alloc.h \ - ../include/ircd_chattr.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd.h ../include/struct.h \ - ../include/match.h ../include/msg.h ../include/numeric.h \ - ../include/random.h ../include/send.h ../include/struct.h \ - ../include/sys.h + ../include/capab.h ../include/ircd_features.h ../include/channel.h \ + ../include/ircd_alloc.h ../include/ircd_chattr.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/ircd.h \ + ../include/struct.h ../include/match.h ../include/msg.h \ + ../include/numeric.h ../include/random.h ../include/send.h \ + ../include/struct.h ../include/sys.h ircd.o: ircd.c ../config.h ../include/ircd.h ../include/struct.h \ ../include/ircd_defs.h ../include/IPcheck.h ../include/class.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/client.h ../include/crule.h \ - ../include/destruct_event.h ../include/channel.h ../include/hash.h \ - ../include/ircd_alloc.h ../include/ircd_events.h \ + ../include/capab.h ../include/ircd_features.h ../include/client.h \ + ../include/crule.h ../include/destruct_event.h ../include/channel.h \ + ../include/hash.h ../include/ircd_alloc.h ../include/ircd_events.h \ ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ ../include/ircd_signal.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/ircd_crypt.h ../include/jupe.h \ @@ -459,34 +468,44 @@ ircd_features.o: ircd_features.c ../config.h ../include/ircd_features.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/class.h ../include/client.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ - ../include/capab.h ../include/client.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/motd.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/random.h ../include/s_bsd.h ../include/s_debug.h \ - ../include/s_misc.h ../include/s_stats.h ../include/send.h \ - ../include/struct.h ../include/sys.h ../include/whowas.h + ../include/capab.h ../include/ircd_features.h ../include/client.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/motd.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/random.h ../include/s_bsd.h \ + ../include/s_debug.h ../include/s_misc.h ../include/s_stats.h \ + ../include/send.h ../include/struct.h ../include/sys.h \ + ../include/whowas.h ircd_lexer.o: ircd_lexer.c ../config.h ../include/ircd.h \ ../include/struct.h ../include/ircd_defs.h ../include/ircd_alloc.h \ ../include/ircd_log.h ../include/ircd_string.h ../include/ircd_chattr.h \ ../include/s_conf.h ../include/client.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ - ../include/res.h ../include/capab.h y.tab.h + ../include/res.h ../include/capab.h ../include/ircd_features.h y.tab.h ircd_log.o: ircd_log.c ../config.h ../include/ircd_log.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ - ../include/res.h ../include/capab.h ../include/ircd_alloc.h \ - ../include/ircd_reply.h ../include/ircd_snprintf.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/ircd.h \ - ../include/struct.h ../include/numeric.h ../include/s_debug.h \ - ../include/send.h ../include/struct.h + ../include/res.h ../include/capab.h ../include/ircd_features.h \ + ../include/ircd_alloc.h ../include/ircd_reply.h \ + ../include/ircd_snprintf.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/ircd.h ../include/struct.h \ + ../include/numeric.h ../include/s_debug.h ../include/send.h \ + ../include/struct.h +ircd_netconf.o: ircd_netconf.c ../config.h ../include/client.h \ + ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_netconf.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_debug.h ../include/send.h ircd_relay.o: ircd_relay.c ../config.h ../include/ircd_relay.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_features.h \ ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/match.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_debug.h ../include/s_misc.h \ @@ -494,21 +513,21 @@ ircd_relay.o: ircd_relay.c ../config.h ../include/ircd_relay.h \ ircd_reply.o: ircd_reply.c ../config.h ../include/ircd_reply.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ - ../include/res.h ../include/capab.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_snprintf.h \ - ../include/msg.h ../include/msgq.h ../include/numeric.h \ - ../include/s_conf.h ../include/client.h ../include/s_debug.h \ - ../include/send.h + ../include/res.h ../include/capab.h ../include/ircd_features.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_snprintf.h ../include/msg.h ../include/msgq.h \ + ../include/numeric.h ../include/s_conf.h ../include/client.h \ + ../include/s_debug.h ../include/send.h ircd_res.o: ircd_res.c ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h ../config.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/ircd_alloc.h ../include/ircd_log.h ../include/ircd_osdep.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_features.h ../include/ircd_alloc.h ../include/ircd_log.h \ + ../include/ircd_osdep.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/ircd_snprintf.h ../include/ircd.h \ ../include/struct.h ../include/numeric.h ../include/fileio.h \ ../include/random.h ../include/s_bsd.h ../include/s_debug.h \ - ../include/s_stats.h ../include/ircd_features.h ../include/send.h \ - ../include/sys.h ../include/res.h ../include/ircd_reslib.h + ../include/s_stats.h ../include/send.h ../include/sys.h ../include/res.h \ + ../include/ircd_reslib.h ircd_reslib.o: ircd_reslib.c ../include/ircd.h ../include/struct.h \ ../include/ircd_defs.h ../include/res.h ../config.h \ ../include/ircd_reslib.h ../include/ircd_defs.h ../include/fileio.h \ @@ -518,31 +537,31 @@ ircd_signal.o: ircd_signal.c ../config.h ../include/ircd.h \ ../include/ircd_events.h ../include/ircd_log.h ../include/ircd_signal.h \ ../include/s_conf.h ../include/client.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h + ../include/capab.h ../include/ircd_features.h ircd_snprintf.o: ircd_snprintf.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/channel.h ../include/ircd_log.h \ - ../include/ircd_snprintf.h ../include/struct.h + ../include/capab.h ../include/ircd_features.h ../include/channel.h \ + ../include/ircd_log.h ../include/ircd_snprintf.h ../include/struct.h ircd_string.o: ircd_string.c ../config.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/ircd_defs.h ../include/ircd_chattr.h \ ../include/ircd_log.h ../include/res.h chattr.tab.c jupe.o: jupe.c ../config.h ../include/jupe.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_bsd.h \ - ../include/s_misc.h ../include/send.h ../include/struct.h \ - ../include/sys.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_bsd.h ../include/s_misc.h ../include/send.h \ + ../include/struct.h ../include/sys.h list.o: list.c ../config.h ../include/list.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_events.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_events.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/listener.h ../include/match.h \ ../include/numeric.h ../include/res.h ../include/s_auth.h \ ../include/s_bsd.h ../include/s_conf.h ../include/client.h \ @@ -551,177 +570,193 @@ list.o: list.c ../config.h ../include/list.h ../include/client.h \ listener.o: listener.c ../config.h ../include/listener.h \ ../include/ircd_defs.h ../include/ircd_events.h ../include/res.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/capab.h ../include/client.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_events.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_osdep.h ../include/ircd_reply.h \ - ../include/ircd_snprintf.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/numeric.h \ - ../include/s_bsd.h ../include/s_conf.h ../include/s_misc.h \ - ../include/s_stats.h ../include/send.h ../include/sys.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/client.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/ircd_events.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_osdep.h \ + ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/numeric.h ../include/s_bsd.h ../include/s_conf.h \ + ../include/s_misc.h ../include/s_stats.h ../include/send.h \ + ../include/sys.h m_account.o: m_account.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numnicks.h \ - ../include/s_debug.h ../include/s_user.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numnicks.h ../include/s_debug.h ../include/s_user.h \ + ../include/send.h m_admin.o: m_admin.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ - ../include/client.h ../include/s_user.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_conf.h ../include/client.h ../include/s_user.h m_asll.o: m_asll.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ - ../include/match.h ../include/msg.h ../include/send.h ../include/s_bsd.h \ - ../include/s_user.h + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/numeric.h \ + ../include/numnicks.h ../include/match.h ../include/msg.h \ + ../include/send.h ../include/s_bsd.h ../include/s_user.h m_away.o: m_away.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_user.h ../include/send.h + ../include/ircd_features.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ + ../include/send.h m_burst.o: m_burst.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ - ../include/match.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_conf.h ../include/client.h \ - ../include/s_misc.h ../include/send.h ../include/struct.h \ - ../include/ircd_snprintf.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/list.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_conf.h ../include/client.h ../include/s_misc.h \ + ../include/send.h ../include/struct.h ../include/ircd_snprintf.h m_cap.o: m_cap.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_chattr.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_snprintf.h \ - ../include/ircd_string.h ../include/msg.h ../include/numeric.h \ - ../include/send.h ../include/s_auth.h ../include/s_user.h + ../include/ircd_features.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_chattr.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_snprintf.h ../include/ircd_string.h ../include/msg.h \ + ../include/numeric.h ../include/send.h ../include/s_auth.h \ + ../include/s_user.h m_clearmode.o: m_clearmode.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/channel.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_conf.h ../include/client.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/channel.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/list.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ + ../include/client.h ../include/send.h m_close.o: m_close.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/numeric.h \ - ../include/s_bsd.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/numeric.h ../include/s_bsd.h ../include/send.h +m_config.o: m_config.c ../config.h ../include/client.h \ + ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_netconf.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/send.h \ + ../include/s_debug.h m_connect.o: m_connect.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/crule.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/jupe.h ../include/match.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_bsd.h ../include/s_conf.h ../include/client.h \ - ../include/s_user.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/crule.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/jupe.h \ + ../include/match.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_bsd.h ../include/s_conf.h \ + ../include/client.h ../include/s_user.h ../include/send.h m_cprivmsg.o: m_cprivmsg.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/s_user.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h + ../include/capab.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/s_user.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_features.h m_create.o: m_create.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_debug.h ../include/s_misc.h \ ../include/s_user.h ../include/send.h m_defaults.o: m_defaults.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h ../include/supported.h \ - ../include/channel.h ../include/version.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/numeric.h ../include/numnicks.h ../include/send.h \ + ../include/supported.h ../include/channel.h ../include/version.h m_destruct.o: m_destruct.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/send.h \ - ../include/channel.h ../include/destruct_event.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/send.h ../include/channel.h \ + ../include/destruct_event.h m_desynch.o: m_desynch.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_bsd.h \ - ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_bsd.h ../include/send.h m_die.o: m_die.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_features.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_bsd.h ../include/send.h m_endburst.o: m_endburst.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/send.h m_error.o: m_error.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ ../include/s_debug.h ../include/s_misc.h ../include/send.h m_get.o: m_get.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ + ../include/send.h m_gline.o: m_gline.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/gline.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ - ../include/client.h ../include/s_debug.h ../include/s_misc.h \ - ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/gline.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_conf.h ../include/client.h ../include/s_debug.h \ + ../include/s_misc.h ../include/send.h m_help.o: m_help.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/send.h m_info.o: m_info.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_features.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_misc.h ../include/s_user.h \ ../include/s_conf.h ../include/client.h ../include/send.h \ @@ -729,25 +764,25 @@ m_info.o: m_info.c ../config.h ../include/client.h ../include/ircd_defs.h \ m_invite.o: m_invite.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/list.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ - ../include/send.h ../include/struct.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_user.h ../include/send.h ../include/struct.h m_ison.o: m_ison.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msgq.h ../include/numeric.h \ - ../include/send.h + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msgq.h \ + ../include/numeric.h ../include/send.h m_join.o: m_join.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/gline.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/gline.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_features.h \ ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/msg.h ../include/numeric.h ../include/numnicks.h \ ../include/s_debug.h ../include/s_user.h ../include/send.h \ @@ -755,351 +790,362 @@ m_join.o: m_join.c ../config.h ../include/channel.h \ m_jupe.o: m_jupe.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/jupe.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_features.h ../include/jupe.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ ../include/client.h ../include/s_misc.h ../include/send.h m_kick.o: m_kick.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/send.h ../include/ircd_features.h m_kill.o: m_kill.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_snprintf.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_misc.h ../include/send.h \ - ../include/whowas.h + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_misc.h \ + ../include/send.h ../include/whowas.h m_links.o: m_links.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_defs.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_defs.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ ../include/send.h ../include/struct.h m_list.o: m_list.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_bsd.h ../include/send.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/ircd_chattr.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_bsd.h ../include/send.h m_lusers.o: m_lusers.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ - ../include/ircd_features.h ../include/s_user.h ../include/s_serv.h \ - ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/querycmds.h ../include/s_user.h \ + ../include/s_serv.h ../include/send.h m_map.o: m_map.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_defs.h \ - ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_snprintf.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/list.h ../include/match.h \ - ../include/msg.h ../include/numeric.h ../include/s_user.h \ - ../include/s_serv.h ../include/send.h ../include/querycmds.h \ - ../include/ircd_features.h + ../include/ircd_features.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_defs.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ + ../include/match.h ../include/msg.h ../include/numeric.h \ + ../include/s_user.h ../include/s_serv.h ../include/send.h \ + ../include/querycmds.h m_mode.o: m_mode.c ../config.h ../include/handlers.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_conf.h ../include/client.h \ - ../include/s_debug.h ../include/s_user.h ../include/send.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ + ../include/client.h ../include/s_debug.h ../include/s_user.h \ + ../include/send.h m_motd.o: m_motd.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/motd.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_conf.h ../include/client.h ../include/class.h \ - ../include/s_user.h ../include/send.h + ../include/ircd_features.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/motd.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_conf.h ../include/client.h \ + ../include/class.h ../include/s_user.h ../include/send.h m_names.o: m_names.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_user.h ../include/send.h m_nick.o: m_nick.c ../config.h ../include/IPcheck.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_chattr.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ - ../include/send.h ../include/sys.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_chattr.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_user.h ../include/send.h ../include/sys.h m_notice.o: m_notice.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/handlers.h ../include/ircd_chattr.h \ - ../include/ircd_log.h ../include/ircd_relay.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/handlers.h \ + ../include/ircd_chattr.h ../include/ircd_log.h ../include/ircd_relay.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/send.h m_oper.o: m_oper.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/ircd_crypt.h ../include/msg.h \ ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ - ../include/ircd_features.h ../include/s_conf.h ../include/client.h \ - ../include/s_debug.h ../include/s_user.h ../include/s_misc.h \ - ../include/send.h + ../include/s_conf.h ../include/client.h ../include/s_debug.h \ + ../include/s_user.h ../include/s_misc.h ../include/send.h m_opmode.o: m_opmode.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/channel.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/querycmds.h ../include/ircd_features.h \ + ../include/capab.h ../include/ircd_features.h ../include/channel.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ ../include/send.h ../include/s_conf.h ../include/client.h \ ../include/s_user.h m_part.o: m_part.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ - ../include/send.h + ../include/send.h ../include/s_user.h m_pass.o: m_pass.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/s_auth.h ../include/send.h + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/s_auth.h \ + ../include/send.h m_ping.o: m_ping.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/hash.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/ircd.h \ - ../include/struct.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/opercmds.h ../include/s_debug.h \ - ../include/send.h + ../include/ircd_features.h ../include/hash.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/ircd.h ../include/struct.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/opercmds.h ../include/s_debug.h ../include/send.h m_pong.o: m_pong.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/opercmds.h ../include/s_auth.h \ - ../include/s_user.h ../include/send.h + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/opercmds.h \ + ../include/s_auth.h ../include/s_user.h ../include/send.h m_privmsg.o: m_privmsg.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_features.h \ ../include/ircd_log.h ../include/ircd_relay.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/match.h ../include/msg.h \ ../include/numeric.h ../include/send.h m_privs.o: m_privs.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/send.h m_proto.o: m_proto.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_debug.h \ - ../include/s_misc.h ../include/send.h ../include/supported.h \ - ../include/channel.h ../include/version.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_chattr.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_debug.h ../include/s_misc.h ../include/send.h \ + ../include/supported.h ../include/channel.h ../include/version.h m_pseudo.o: m_pseudo.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_relay.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/ircd_snprintf.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ - ../include/client.h ../include/s_user.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_relay.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/ircd_snprintf.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_conf.h ../include/client.h \ + ../include/s_user.h m_quit.o: m_quit.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/struct.h ../include/s_misc.h \ - ../include/ircd_reply.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/struct.h \ + ../include/s_misc.h ../include/s_user.h ../include/ircd_reply.h m_rehash.o: m_rehash.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/motd.h ../include/numeric.h \ - ../include/s_conf.h ../include/client.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/motd.h \ + ../include/numeric.h ../include/s_conf.h ../include/client.h \ + ../include/send.h m_reset.o: m_reset.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ ../include/send.h m_restart.o: m_restart.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ - ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/numeric.h \ + ../include/numnicks.h ../include/send.h m_rping.o: m_rping.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/opercmds.h \ - ../include/s_user.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/opercmds.h ../include/s_user.h \ + ../include/send.h m_rpong.o: m_rpong.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/opercmds.h \ - ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/opercmds.h ../include/send.h m_server.o: m_server.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_features.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/jupe.h ../include/list.h \ - ../include/match.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/querycmds.h ../include/ircd_features.h \ + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_features.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/jupe.h \ + ../include/list.h ../include/match.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ ../include/s_bsd.h ../include/s_conf.h ../include/client.h \ ../include/s_debug.h ../include/s_misc.h ../include/s_serv.h \ ../include/send.h ../include/userload.h m_set.o: m_set.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ + ../include/send.h m_settime.o: m_settime.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_snprintf.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ ../include/msg.h ../include/numeric.h ../include/numnicks.h \ ../include/s_user.h ../include/send.h ../include/struct.h m_silence.o: m_silence.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_snprintf.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_user.h ../include/send.h ../include/struct.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_snprintf.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/list.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ + ../include/send.h ../include/struct.h m_squit.o: m_squit.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_chattr.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h ../include/numeric.h \ - ../include/numnicks.h ../include/match.h ../include/s_debug.h \ - ../include/s_misc.h ../include/s_user.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_chattr.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/numeric.h ../include/numnicks.h ../include/match.h \ + ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ + ../include/send.h m_stats.o: m_stats.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/s_stats.h ../include/s_user.h \ - ../include/send.h ../include/struct.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/s_stats.h ../include/s_user.h ../include/send.h \ + ../include/struct.h m_time.o: m_time.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_misc.h ../include/s_user.h \ - ../include/send.h + ../include/ircd_features.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_misc.h \ + ../include/s_user.h ../include/send.h m_topic.o: m_topic.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/send.h m_trace.o: m_trace.c ../config.h ../include/class.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/client.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_bsd.h \ - ../include/s_conf.h ../include/s_user.h ../include/send.h \ - ../include/version.h + ../include/capab.h ../include/ircd_features.h ../include/client.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_bsd.h ../include/s_conf.h ../include/s_user.h \ + ../include/send.h ../include/version.h m_uping.o: m_uping.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_conf.h ../include/client.h ../include/s_user.h \ - ../include/send.h ../include/uping.h + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ + ../include/client.h ../include/s_user.h ../include/send.h \ + ../include/uping.h m_user.o: m_user.c ../config.h ../include/handlers.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_auth.h ../include/s_debug.h ../include/s_misc.h \ - ../include/s_user.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_auth.h ../include/s_debug.h \ + ../include/s_misc.h ../include/s_user.h ../include/send.h m_userhost.o: m_userhost.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msgq.h \ - ../include/numeric.h ../include/s_user.h ../include/struct.h + ../include/capab.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msgq.h ../include/numeric.h \ + ../include/s_user.h ../include/struct.h m_userip.o: m_userip.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/msgq.h ../include/numeric.h \ - ../include/s_user.h ../include/struct.h + ../include/capab.h ../include/ircd_features.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/msgq.h \ + ../include/numeric.h ../include/s_user.h ../include/struct.h m_version.o: m_version.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_snprintf.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ ../include/msg.h ../include/numeric.h ../include/numnicks.h \ ../include/s_debug.h ../include/s_user.h ../include/send.h \ @@ -1107,79 +1153,82 @@ m_version.o: m_version.c ../config.h ../include/client.h \ m_wallchops.o: m_wallchops.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_user.h ../include/send.h m_wallops.o: m_wallops.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/send.h m_wallusers.o: m_wallusers.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/send.h m_wallvoices.o: m_wallvoices.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_user.h ../include/send.h m_webirc.o: m_webirc.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_features.h ../include/ircd_reply.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_features.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/s_auth.h \ ../include/s_conf.h ../include/client.h ../include/s_misc.h m_who.o: m_who.c ../config.h ../include/channel.h ../include/ircd_defs.h \ ../include/res.h ../include/client.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_features.h \ ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/match.h ../include/numeric.h ../include/numnicks.h \ ../include/send.h ../include/whocmds.h m_whois.o: m_whois.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ - ../include/client.h ../include/s_user.h ../include/send.h \ - ../include/whocmds.h + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_conf.h ../include/client.h ../include/s_user.h \ + ../include/send.h ../include/whocmds.h m_whowas.o: m_whowas.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/capab.h ../include/ircd_features.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_user.h ../include/s_misc.h \ ../include/send.h ../include/whowas.h m_xquery.o: m_xquery.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/send.h m_xreply.o: m_xreply.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_auth.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_auth.h \ + ../include/send.h match.o: match.c ../config.h ../include/match.h ../include/res.h \ ../include/ircd_chattr.h ../include/ircd_string.h \ ../include/ircd_snprintf.h @@ -1187,15 +1236,15 @@ memdebug.o: memdebug.c ../include/ircd.h ../include/struct.h \ ../include/ircd_defs.h ../include/ircd_alloc.h ../include/ircd_log.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../config.h ../include/ircd_handler.h \ - ../include/res.h ../include/capab.h ../include/s_debug.h \ - ../include/send.h + ../include/res.h ../include/capab.h ../include/ircd_features.h \ + ../include/s_debug.h ../include/send.h motd.o: motd.c ../config.h ../include/motd.h ../include/res.h \ ../include/class.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ - ../include/ircd_handler.h ../include/capab.h ../include/client.h \ - ../include/fileio.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ + ../include/client.h ../include/fileio.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ ../include/s_debug.h ../include/s_user.h ../include/s_stats.h \ @@ -1204,21 +1253,24 @@ msgq.o: msgq.c ../config.h ../include/msgq.h ../include/ircd_defs.h \ ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ ../include/ircd_defs.h ../include/ircd_features.h ../include/ircd_log.h \ ../include/ircd_reply.h ../include/ircd_snprintf.h ../include/numeric.h \ - ../include/send.h ../include/s_debug.h ../include/s_stats.h + ../include/send.h ../include/client.h ../include/dbuf.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ + ../include/capab.h ../include/ircd_features.h ../include/s_debug.h \ + ../include/s_stats.h numnicks.o: numnicks.c ../config.h ../include/numnicks.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ - ../include/res.h ../include/capab.h ../include/client.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_log.h ../include/ircd_string.h ../include/ircd_chattr.h \ - ../include/match.h ../include/s_bsd.h ../include/s_debug.h \ - ../include/s_misc.h ../include/struct.h + ../include/res.h ../include/capab.h ../include/ircd_features.h \ + ../include/client.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/ircd_log.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/match.h ../include/s_bsd.h \ + ../include/s_debug.h ../include/s_misc.h ../include/struct.h opercmds.o: opercmds.c ../config.h ../include/opercmds.h \ ../include/class.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/client.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_reply.h \ + ../include/ircd_features.h ../include/client.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/listener.h ../include/match.h \ ../include/msg.h ../include/numeric.h ../include/numnicks.h \ ../include/s_conf.h ../include/send.h ../include/struct.h @@ -1228,69 +1280,70 @@ os_generic.o: os_generic.c ../config.h ../include/ircd_osdep.h \ packet.o: packet.c ../config.h ../include/packet.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_log.h ../include/parse.h \ - ../include/s_bsd.h ../include/s_misc.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_log.h \ + ../include/parse.h ../include/s_bsd.h ../include/s_misc.h \ + ../include/send.h parse.o: parse.c ../config.h ../include/parse.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/channel.h ../include/handlers.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h \ + ../include/capab.h ../include/ircd_features.h ../include/channel.h \ + ../include/handlers.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_chattr.h \ ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/opercmds.h ../include/querycmds.h \ - ../include/ircd_features.h ../include/res.h ../include/s_bsd.h \ - ../include/s_conf.h ../include/client.h ../include/s_debug.h \ - ../include/s_misc.h ../include/s_numeric.h ../include/s_user.h \ - ../include/send.h ../include/struct.h ../include/sys.h \ - ../include/whocmds.h ../include/whowas.h + ../include/res.h ../include/s_bsd.h ../include/s_conf.h \ + ../include/client.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_numeric.h ../include/s_user.h ../include/send.h \ + ../include/struct.h ../include/sys.h ../include/whocmds.h \ + ../include/whowas.h querycmds.o: querycmds.c ../config.h ../include/querycmds.h \ ../include/ircd_features.h random.o: random.c ../config.h ../include/random.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd_log.h ../include/ircd_md5.h \ - ../include/ircd_reply.h ../include/send.h + ../include/capab.h ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_md5.h ../include/ircd_reply.h ../include/send.h s_auth.o: s_auth.c ../config.h ../include/s_auth.h \ ../include/ircd_events.h ../include/class.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_handler.h ../include/res.h ../include/capab.h \ - ../include/client.h ../include/IPcheck.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_chattr.h \ - ../include/ircd_events.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_osdep.h ../include/ircd_reply.h \ - ../include/ircd_snprintf.h ../include/ircd_string.h ../include/list.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/querycmds.h ../include/ircd_features.h ../include/random.h \ - ../include/res.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/s_debug.h ../include/s_misc.h ../include/s_stats.h \ - ../include/s_user.h ../include/send.h + ../include/ircd_features.h ../include/client.h ../include/IPcheck.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/ircd_chattr.h ../include/ircd_events.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_osdep.h \ + ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/ircd_string.h ../include/list.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ + ../include/random.h ../include/res.h ../include/s_bsd.h \ + ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_stats.h ../include/s_user.h ../include/send.h s_bsd.o: s_bsd.c ../config.h ../include/s_bsd.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/IPcheck.h ../include/channel.h \ - ../include/class.h ../include/client.h ../include/hash.h \ - ../include/ircd_alloc.h ../include/ircd_log.h ../include/ircd_features.h \ - ../include/ircd_osdep.h ../include/ircd_reply.h \ - ../include/ircd_snprintf.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/ircd.h ../include/struct.h \ - ../include/list.h ../include/listener.h ../include/msg.h \ - ../include/msgq.h ../include/numeric.h ../include/numnicks.h \ - ../include/packet.h ../include/parse.h ../include/querycmds.h \ - ../include/ircd_features.h ../include/res.h ../include/s_auth.h \ + ../include/capab.h ../include/ircd_features.h ../include/IPcheck.h \ + ../include/channel.h ../include/class.h ../include/client.h \ + ../include/hash.h ../include/ircd_alloc.h ../include/ircd_log.h \ + ../include/ircd_features.h ../include/ircd_osdep.h \ + ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/ircd.h \ + ../include/struct.h ../include/list.h ../include/listener.h \ + ../include/msg.h ../include/msgq.h ../include/numeric.h \ + ../include/numnicks.h ../include/packet.h ../include/parse.h \ + ../include/querycmds.h ../include/res.h ../include/s_auth.h \ ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \ ../include/s_user.h ../include/send.h ../include/struct.h \ ../include/sys.h ../include/uping.h ../include/version.h s_conf.o: s_conf.c ../config.h ../include/s_conf.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/IPcheck.h ../include/class.h \ - ../include/client.h ../include/crule.h ../include/ircd_features.h \ - ../include/fileio.h ../include/gline.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_chattr.h ../include/ircd_lexer.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/capab.h ../include/ircd_features.h ../include/IPcheck.h \ + ../include/class.h ../include/client.h ../include/crule.h \ + ../include/ircd_features.h ../include/fileio.h ../include/gline.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/ircd_chattr.h ../include/ircd_lexer.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_snprintf.h \ ../include/ircd_string.h ../include/list.h ../include/listener.h \ ../include/match.h ../include/motd.h ../include/numeric.h \ ../include/numnicks.h ../include/opercmds.h ../include/parse.h \ @@ -1301,92 +1354,94 @@ s_debug.o: s_debug.c ../config.h ../include/s_debug.h \ ../include/ircd_defs.h ../include/channel.h ../include/res.h \ ../include/class.h ../include/client.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ - ../include/capab.h ../include/client.h ../include/gline.h \ - ../include/hash.h ../include/ircd_alloc.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_osdep.h ../include/ircd_reply.h \ - ../include/ircd.h ../include/struct.h ../include/jupe.h \ - ../include/list.h ../include/listener.h ../include/motd.h \ - ../include/msgq.h ../include/numeric.h ../include/numnicks.h \ - ../include/res.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/s_user.h ../include/s_stats.h ../include/send.h \ - ../include/struct.h ../include/sys.h ../include/whowas.h + ../include/capab.h ../include/ircd_features.h ../include/client.h \ + ../include/gline.h ../include/hash.h ../include/ircd_alloc.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_osdep.h \ + ../include/ircd_reply.h ../include/ircd.h ../include/struct.h \ + ../include/jupe.h ../include/list.h ../include/listener.h \ + ../include/motd.h ../include/msgq.h ../include/numeric.h \ + ../include/numnicks.h ../include/res.h ../include/s_bsd.h \ + ../include/s_conf.h ../include/s_user.h ../include/s_stats.h \ + ../include/send.h ../include/struct.h ../include/sys.h \ + ../include/whowas.h s_err.o: s_err.c ../config.h ../include/numeric.h ../include/ircd_log.h \ ../include/s_debug.h ../include/ircd_defs.h s_misc.o: s_misc.c ../config.h ../include/s_misc.h ../include/IPcheck.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_snprintf.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ ../include/match.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/parse.h ../include/querycmds.h \ - ../include/ircd_features.h ../include/res.h ../include/s_auth.h \ - ../include/s_bsd.h ../include/s_conf.h ../include/client.h \ - ../include/s_debug.h ../include/s_stats.h ../include/s_user.h \ - ../include/send.h ../include/struct.h ../include/sys.h \ - ../include/uping.h ../include/userload.h + ../include/res.h ../include/s_auth.h ../include/s_bsd.h \ + ../include/s_conf.h ../include/client.h ../include/s_debug.h \ + ../include/s_stats.h ../include/s_user.h ../include/send.h \ + ../include/struct.h ../include/sys.h ../include/uping.h \ + ../include/userload.h s_numeric.o: s_numeric.c ../config.h ../include/s_numeric.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_features.h ../include/ircd_snprintf.h \ - ../include/numnicks.h ../include/send.h ../include/struct.h + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_snprintf.h ../include/numnicks.h ../include/send.h \ + ../include/struct.h s_serv.o: s_serv.c ../config.h ../include/s_serv.h ../include/IPcheck.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/capab.h \ - ../include/gline.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/ircd_snprintf.h \ - ../include/ircd_crypt.h ../include/jupe.h ../include/list.h \ - ../include/match.h ../include/msg.h ../include/msgq.h \ + ../include/ircd_features.h ../include/gline.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/ircd_log.h ../include/ircd_netconf.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/ircd_snprintf.h ../include/ircd_crypt.h ../include/jupe.h \ + ../include/list.h ../include/match.h ../include/msg.h ../include/msgq.h \ ../include/numeric.h ../include/numnicks.h ../include/parse.h \ - ../include/querycmds.h ../include/ircd_features.h ../include/s_bsd.h \ - ../include/s_conf.h ../include/client.h ../include/s_debug.h \ - ../include/s_misc.h ../include/s_user.h ../include/send.h \ - ../include/struct.h ../include/sys.h ../include/userload.h + ../include/querycmds.h ../include/s_bsd.h ../include/s_conf.h \ + ../include/client.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_user.h ../include/send.h ../include/struct.h \ + ../include/sys.h ../include/userload.h s_stats.o: s_stats.c ../config.h ../include/class.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/client.h ../include/gline.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_events.h \ - ../include/ircd_features.h ../include/ircd_crypt.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h ../include/listener.h \ - ../include/list.h ../include/match.h ../include/motd.h ../include/msg.h \ - ../include/msgq.h ../include/numeric.h ../include/numnicks.h \ - ../include/querycmds.h ../include/ircd_features.h ../include/res.h \ - ../include/s_auth.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/s_debug.h ../include/s_misc.h ../include/s_serv.h \ - ../include/s_stats.h ../include/s_user.h ../include/send.h \ - ../include/struct.h ../include/userload.h + ../include/capab.h ../include/ircd_features.h ../include/client.h \ + ../include/gline.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_netconf.h \ + ../include/ircd_events.h ../include/ircd_features.h \ + ../include/ircd_crypt.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/listener.h ../include/list.h \ + ../include/match.h ../include/motd.h ../include/msg.h ../include/msgq.h \ + ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ + ../include/res.h ../include/s_auth.h ../include/s_bsd.h \ + ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_serv.h ../include/s_stats.h ../include/s_user.h \ + ../include/send.h ../include/struct.h ../include/userload.h s_user.o: s_user.c ../config.h ../include/s_user.h ../include/IPcheck.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/class.h ../include/client.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ - ../include/capab.h ../include/client.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_snprintf.h \ - ../include/ircd_string.h ../include/list.h ../include/match.h \ - ../include/motd.h ../include/msg.h ../include/msgq.h \ + ../include/capab.h ../include/ircd_features.h ../include/client.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/ircd_chattr.h \ + ../include/ircd_features.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_snprintf.h ../include/ircd_string.h ../include/list.h \ + ../include/match.h ../include/motd.h ../include/msg.h ../include/msgq.h \ ../include/numeric.h ../include/numnicks.h ../include/parse.h \ - ../include/querycmds.h ../include/ircd_features.h ../include/random.h \ - ../include/s_auth.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/s_debug.h ../include/s_misc.h ../include/s_serv.h \ - ../include/send.h ../include/struct.h ../include/supported.h \ - ../include/channel.h ../include/sys.h ../include/userload.h \ - ../include/version.h ../include/whowas.h ../include/handlers.h -send.o: send.c ../config.h ../include/send.h ../include/channel.h \ - ../include/ircd_defs.h ../include/res.h ../include/class.h \ - ../include/client.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_events.h ../include/ircd_handler.h ../include/capab.h \ - ../include/client.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_features.h ../include/ircd_log.h \ + ../include/querycmds.h ../include/random.h ../include/s_auth.h \ + ../include/s_bsd.h ../include/s_conf.h ../include/s_debug.h \ + ../include/s_misc.h ../include/s_serv.h ../include/send.h \ + ../include/struct.h ../include/supported.h ../include/channel.h \ + ../include/sys.h ../include/userload.h ../include/version.h \ + ../include/whowas.h ../include/handlers.h +send.o: send.c ../config.h ../include/send.h ../include/client.h \ + ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ + ../include/capab.h ../include/ircd_features.h ../include/channel.h \ + ../include/class.h ../include/client.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ ../include/ircd_snprintf.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/list.h ../include/match.h \ ../include/msg.h ../include/numnicks.h ../include/parse.h \ @@ -1395,9 +1450,9 @@ send.o: send.c ../config.h ../include/send.h ../include/channel.h \ uping.o: uping.c ../config.h ../include/uping.h ../include/ircd_defs.h \ ../include/ircd_events.h ../include/res.h ../include/client.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_events.h ../include/ircd_log.h \ - ../include/ircd_osdep.h ../include/ircd_string.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_events.h \ + ../include/ircd_log.h ../include/ircd_osdep.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ ../include/numeric.h ../include/numnicks.h ../include/s_bsd.h \ ../include/s_conf.h ../include/client.h ../include/s_debug.h \ @@ -1406,30 +1461,30 @@ uping.o: uping.c ../config.h ../include/uping.h ../include/ircd_defs.h \ userload.o: userload.c ../config.h ../include/userload.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ - ../include/res.h ../include/capab.h ../include/ircd.h \ - ../include/struct.h ../include/msg.h ../include/numnicks.h \ - ../include/querycmds.h ../include/ircd_features.h ../include/s_misc.h \ + ../include/res.h ../include/capab.h ../include/ircd_features.h \ + ../include/ircd.h ../include/struct.h ../include/msg.h \ + ../include/numnicks.h ../include/querycmds.h ../include/s_misc.h \ ../include/s_stats.h ../include/send.h ../include/struct.h \ ../include/sys.h whocmds.o: whocmds.c ../config.h ../include/whocmds.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/capab.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/ircd_features.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_features.h \ ../include/ircd_reply.h ../include/ircd_snprintf.h \ ../include/ircd_string.h ../include/list.h ../include/match.h \ ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ - ../include/ircd_features.h ../include/random.h ../include/s_bsd.h \ - ../include/s_conf.h ../include/client.h ../include/s_misc.h \ - ../include/s_user.h ../include/send.h ../include/struct.h \ - ../include/sys.h ../include/userload.h ../include/version.h \ - ../include/whowas.h ../include/msg.h + ../include/random.h ../include/s_bsd.h ../include/s_conf.h \ + ../include/client.h ../include/s_misc.h ../include/s_user.h \ + ../include/send.h ../include/struct.h ../include/sys.h \ + ../include/userload.h ../include/version.h ../include/whowas.h \ + ../include/msg.h whowas.o: whowas.c ../config.h ../include/whowas.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_chattr.h \ ../include/ircd_features.h ../include/ircd_log.h \ ../include/ircd_string.h ../include/list.h ../include/numeric.h \ ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ @@ -1437,18 +1492,18 @@ whowas.o: whowas.c ../config.h ../include/whowas.h ../include/client.h \ y.tab.o: y.tab.c ../config.h ../include/s_conf.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/class.h ../include/client.h \ - ../include/crule.h ../include/fileio.h ../include/gline.h \ - ../include/hash.h ../include/IPcheck.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_chattr.h \ - ../include/ircd_features.h ../include/ircd_lexer.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_snprintf.h \ - ../include/ircd_string.h ../include/list.h ../include/listener.h \ - ../include/match.h ../include/motd.h ../include/numeric.h \ - ../include/numnicks.h ../include/opercmds.h ../include/parse.h \ - ../include/res.h ../include/s_auth.h ../include/s_bsd.h \ - ../include/s_debug.h ../include/s_misc.h ../include/send.h \ - ../include/struct.h ../include/sys.h + ../include/capab.h ../include/ircd_features.h ../include/class.h \ + ../include/client.h ../include/crule.h ../include/fileio.h \ + ../include/gline.h ../include/hash.h ../include/IPcheck.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/ircd_lexer.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_snprintf.h ../include/ircd_string.h ../include/list.h \ + ../include/listener.h ../include/match.h ../include/motd.h \ + ../include/numeric.h ../include/numnicks.h ../include/opercmds.h \ + ../include/parse.h ../include/res.h ../include/s_auth.h \ + ../include/s_bsd.h ../include/s_debug.h ../include/s_misc.h \ + ../include/send.h ../include/struct.h ../include/sys.h engine_devpoll.o: engine_devpoll.c ../config.h ../include/ircd_events.h \ ../include/ircd.h ../include/struct.h ../include/ircd_defs.h \ ../include/ircd_alloc.h ../include/ircd_features.h ../include/ircd_log.h \ diff --git a/ircd/ircd_features.c b/ircd/ircd_features.c index 6410099b..53aaa3e1 100644 --- a/ircd/ircd_features.c +++ b/ircd/ircd_features.c @@ -387,6 +387,7 @@ static struct FeatureDesc { F_B(HIS_TRACE, 0, 1, 0), F_B(HIS_STATS_a, 0, 1, 0), F_B(HIS_STATS_c, 0, 1, 0), + F_B(HIS_STATS_C, 0, 1, 0), F_B(HIS_STATS_d, 0, 1, 0), F_B(HIS_STATS_e, 0, 1, 0), F_B(HIS_STATS_f, 0, 1, 0), @@ -397,13 +398,13 @@ static struct FeatureDesc { F_B(HIS_STATS_k, 0, 1, 0), F_B(HIS_STATS_l, 0, 1, 0), F_B(HIS_STATS_L, 0, 1, 0), - F_B(HIS_STATS_M, 0, 1, 0), F_B(HIS_STATS_m, 0, 1, 0), + F_B(HIS_STATS_M, 0, 1, 0), F_B(HIS_STATS_o, 0, 1, 0), F_B(HIS_STATS_p, 0, 1, 0), F_B(HIS_STATS_q, 0, 1, 0), - F_B(HIS_STATS_R, 0, 1, 0), F_B(HIS_STATS_r, 0, 1, 0), + F_B(HIS_STATS_R, 0, 1, 0), F_B(HIS_STATS_t, 0, 1, 0), F_B(HIS_STATS_T, 0, 1, 0), F_B(HIS_STATS_u, 0, 0, 0), diff --git a/ircd/ircd_netconf.c b/ircd/ircd_netconf.c new file mode 100644 index 00000000..a08ad2d3 --- /dev/null +++ b/ircd/ircd_netconf.c @@ -0,0 +1,265 @@ +/* + * IRC - Internet Relay Chat, ircd/ircd_netconf.c + * Copyright (C) 2025 MrIron + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "config.h" + +#include "client.h" +#include "ircd.h" +#include "ircd_alloc.h" +#include "ircd_netconf.h" +#include "ircd_reply.h" +#include "ircd_string.h" +#include "msg.h" +#include "numeric.h" +#include "numnicks.h" +#include "s_debug.h" +#include "send.h" + +#include +#include + +/** Head of the configuration list */ +static struct ConfigEntry *config_list = NULL; + +/** Head of the callback list */ +static struct ConfigCallback *callback_list = NULL; + +/** Find a configuration entry by key + * @param[in] key Configuration key to find + * @return Configuration entry or NULL if not found + */ +static struct ConfigEntry *config_find(const char *key) +{ + struct ConfigEntry *entry; + + assert(key != NULL); + + for (entry = config_list; entry; entry = entry->next) { + if (ircd_strcmp(entry->key, key) == 0) + return entry; + } + + return NULL; +} + +/** Call registered callbacks for a key + * @param[in] key Configuration key that changed + * @param[in] old_value Previous value (NULL if new) + * @param[in] new_value New value + */ +static void config_call_callbacks(const char *key, const char *old_value, const char *new_value) +{ + struct ConfigCallback *cb; + + for (cb = callback_list; cb; cb = cb->next) { + if (ircd_strncmp(key, cb->key_prefix, strlen(cb->key_prefix)) == 0) { + cb->callback(key, old_value, new_value); + } + } +} + +/** Set a configuration option + * @param[in] key Configuration key + * @param[in] value Configuration value + * @param[in] timestamp Timestamp when this config was set + * @return 1 if the value was updated, 0 if it was created, -1 on error + */ +int config_set(const char *key, const char *value, time_t timestamp) +{ + struct ConfigEntry *entry; + char *old_value = NULL; + int result; + + assert(key != NULL); + assert(value != NULL); + + entry = config_find(key); + + if (entry) { + /* Only update if timestamp is newer */ + if (timestamp <= entry->timestamp) + return CONFIG_REJECTED; + + /* Save old value for callbacks */ + DupString(old_value, entry->value); + + /* Check if value actually changed */ + int value_changed = (ircd_strcmp(old_value, value) != 0); + + /* Update existing entry */ + MyFree(entry->value); + DupString(entry->value, value); + entry->timestamp = timestamp; + + result = value_changed ? CONFIG_CHANGED : CONFIG_TIMESTAMP; + } else { + /* Create new entry */ + entry = MyMalloc(sizeof(struct ConfigEntry)); + DupString(entry->key, key); + DupString(entry->value, value); + entry->timestamp = timestamp; + entry->next = config_list; + config_list = entry; + result = CONFIG_CREATED; + } + + Debug((DEBUG_DEBUG, "Config %s: %s = %s (timestamp: %lu)", + (result == CONFIG_CHANGED) ? "changed" : + (result == CONFIG_TIMESTAMP) ? "timestamp updated" : "set", + key, value, (unsigned long)timestamp)); + + /* Call callbacks */ + config_call_callbacks(key, old_value, value); + + if (old_value) + MyFree(old_value); + + return result; +} + +/** Get a configuration value + * @param[in] key Configuration key + * @return Configuration value or NULL if not found + */ +const char *config_get(const char *key) +{ + struct ConfigEntry *entry; + + assert(key != NULL); + + entry = config_find(key); + return entry ? entry->value : NULL; +} + +/** Get the timestamp of a configuration option + * @param[in] key Configuration key + * @return Timestamp or 0 if not found + */ +time_t config_get_timestamp(const char *key) +{ + struct ConfigEntry *entry; + + assert(key != NULL); + + entry = config_find(key); + return entry ? entry->timestamp : 0; +} + +/** Count the number of configuration entries + * @return Number of configuration entries + */ +static int config_count(void) +{ + struct ConfigEntry *entry; + int count = 0; + + for (entry = config_list; entry; entry = entry->next) + count++; + + return count; +} + +/** Register a callback for configuration changes + * @param[in] key_prefix Key prefix to match (e.g., "sasl.") + * @param[in] callback Callback function to call + */ +void config_register_callback(const char *key_prefix, config_callback_f callback) +{ + struct ConfigCallback *cb; + + assert(key_prefix != NULL); + assert(callback != NULL); + + /* Check if callback already exists */ + for (cb = callback_list; cb; cb = cb->next) { + if (ircd_strcmp(cb->key_prefix, key_prefix) == 0) { + cb->callback = callback; + return; + } + } + + /* Create new callback */ + cb = MyMalloc(sizeof(struct ConfigCallback)); + DupString(cb->key_prefix, key_prefix); + cb->callback = callback; + cb->next = callback_list; + callback_list = cb; + + Debug((DEBUG_DEBUG, "Config callback registered for prefix: %s", key_prefix)); +} + +/** Unregister a callback for configuration changes + * @param[in] key_prefix Key prefix that was registered + */ +void config_unregister_callback(const char *key_prefix) +{ + struct ConfigCallback *cb, *prev = NULL; + + assert(key_prefix != NULL); + + for (cb = callback_list; cb; prev = cb, cb = cb->next) { + if (ircd_strcmp(cb->key_prefix, key_prefix) == 0) { + if (prev) + prev->next = cb->next; + else + callback_list = cb->next; + + MyFree(cb->key_prefix); + MyFree(cb); + + Debug((DEBUG_DEBUG, "Config callback unregistered for prefix: %s", key_prefix)); + return; + } + } +} + +/** Burst all configuration entries to a newly connected server + * @param[in] cptr Server to send CF messages to + */ +void config_burst(struct Client *cptr) +{ + struct ConfigEntry *entry; + + for (entry = config_list; entry; entry = entry->next) { + sendcmdto_one(&me, CMD_CONFIG, cptr, "%Tu %s %s", + entry->timestamp, entry->key, entry->value); + } + + Debug((DEBUG_INFO, "Config burst: %d entries sent to %s", + config_count(), cli_name(cptr))); +} + +/** Generate configuration statistics for /STATS C + * @param[in] sptr Client requesting statistics + * @param[in] sd Stats descriptor (unused) + * @param[in] param Additional parameter (unused) + */ +void config_stats(struct Client *sptr, const struct StatDesc *sd, char *param) +{ + struct ConfigEntry *entry; + + for (entry = config_list; entry; entry = entry->next) { + send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, + "%Tu %s :%s", + entry->timestamp, entry->key, entry->value); + } +} \ No newline at end of file diff --git a/ircd/m_config.c b/ircd/m_config.c new file mode 100644 index 00000000..c9d9d3e3 --- /dev/null +++ b/ircd/m_config.c @@ -0,0 +1,94 @@ +/* + * IRC - Internet Relay Chat, ircd/m_config.c + * Copyright (C) 2025 MrIron + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "config.h" + +#include "client.h" +#include "ircd.h" +#include "ircd_alloc.h" +#include "ircd_netconf.h" +#include "ircd_reply.h" +#include "ircd_string.h" +#include "msg.h" +#include "numeric.h" +#include "numnicks.h" +#include "send.h" +#include "s_debug.h" + +#include + +/** Handler for server CONFIG messages + * @param[in] cptr Local client that sent us the message + * @param[in] sptr Original source of the message + * @param[in] parc Number of parameters + * @param[in] parv Parameter vector (source CF timestamp key value) + * @return 0 on success + */ +int ms_config(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) +{ + time_t timestamp; + const char *key, *value; + const char *old_value; + int result; + + if (parc < 4) + return need_more_params(sptr, "CF"); + + timestamp = atol(parv[1]); + key = parv[2]; + value = parv[3]; + + /* Get the old value for comparison */ + old_value = config_get(key); + char *old_value_copy = NULL; + if (old_value) + DupString(old_value_copy, old_value); + + /* Try to set the configuration */ + result = config_set(key, value, timestamp); + + if (result != CONFIG_REJECTED) { + /* Configuration was set or updated, propagate to other servers */ + sendcmdto_serv_butone(sptr, CMD_CONFIG, cptr, "%Tu %s :%s", + timestamp, key, value); + + /* Send notification to operators based on what actually happened */ + if (result == CONFIG_CREATED) { + sendto_opmask_butone(0, SNO_NETWORK, + "Network configuration set: %s = %s", + key, value); + } else if (result == CONFIG_CHANGED) { + sendto_opmask_butone(0, SNO_NETWORK, + "Network configuration updated: %s = %s (was: %s)", + key, value, old_value_copy ? old_value_copy : "(unset)"); + } + + Debug((DEBUG_DEBUG, "NETCONF: %s set %s = %s (timestamp: %Tu)", + cli_name(sptr), key, value, timestamp)); + } + + /* Clean up the copied old value */ + if (old_value_copy) + MyFree(old_value_copy); + + return 0; +} diff --git a/ircd/parse.c b/ircd/parse.c index cfc78ca3..60771e25 100644 --- a/ircd/parse.c +++ b/ircd/parse.c @@ -658,6 +658,13 @@ struct Message msgtab[] = { /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_quit, m_ignore, m_ignore, m_ignore, m_ignore } }, + { + MSG_CONFIG, + TOK_CONFIG, + 0, MAXPARA, 0, 0, NULL, + /* UNREG, CLIENT, SERVER, OPER, SERVICE */ + { m_ignore, m_ignore, ms_config, m_ignore, m_ignore } + }, { 0 } }; diff --git a/ircd/s_serv.c b/ircd/s_serv.c index 2969808b..691c7a0b 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -35,6 +35,7 @@ #include "ircd.h" #include "ircd_alloc.h" #include "ircd_log.h" +#include "ircd_netconf.h" #include "ircd_reply.h" #include "ircd_string.h" #include "ircd_snprintf.h" @@ -197,6 +198,9 @@ int server_estab(struct Client *cptr, struct ConfItem *aconf) gline_burst(cptr); jupe_burst(cptr); + /* Burst server configuration. */ + config_burst(cptr); + /* * Pass on my client information to the new server * diff --git a/ircd/s_stats.c b/ircd/s_stats.c index 07ddf9cb..09f17478 100644 --- a/ircd/s_stats.c +++ b/ircd/s_stats.c @@ -27,6 +27,7 @@ #include "hash.h" #include "ircd.h" #include "ircd_chattr.h" +#include "ircd_netconf.h" #include "ircd_events.h" #include "ircd_features.h" #include "ircd_crypt.h" @@ -558,9 +559,12 @@ struct StatDesc statsinfo[] = { { 'a', "nameservers", STAT_FLAG_OPERFEAT|STAT_FLAG_LOCONLY, FEAT_HIS_STATS_a, report_dns_servers, 0, "DNS servers." }, - { 'c', "connect", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_c, + { 'c', "connect", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_c, stats_configured_links, CONF_SERVER, "Remote server connection lines." }, + { 'C', "config", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_C, + config_stats, 0, + "Network configuration entries." }, { 'd', "maskrules", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_d, stats_crule_list, CRULE_MASK, "Dynamic routing configuration." }, diff --git a/ircd/test/Makefile.in b/ircd/test/Makefile.in index 9831ecc0..388f1abb 100644 --- a/ircd/test/Makefile.in +++ b/ircd/test/Makefile.in @@ -70,7 +70,8 @@ ircd_in_addr_t.o: ircd_in_addr_t.c ../../include/ircd_log.h \ ../../include/numnicks.h ../../include/client.h \ ../../include/ircd_defs.h ../../include/dbuf.h ../../include/msgq.h \ ../../include/ircd_events.h ../../config.h ../../include/ircd_handler.h \ - ../../include/res.h ../../include/capab.h ../../include/res.h + ../../include/res.h ../../include/capab.h ../../include/ircd_features.h \ + ../../include/res.h ircd_match_t.o: ircd_match_t.c ../../include/ircd_log.h \ ../../include/match.h ../../include/res.h ../../config.h ircd_string_t.o: ircd_string_t.c ../../include/ircd_string.h \ @@ -78,4 +79,5 @@ ircd_string_t.o: ircd_string_t.c ../../include/ircd_string.h \ test_stub.o: test_stub.c ../../include/client.h ../../include/ircd_defs.h \ ../../include/dbuf.h ../../include/msgq.h ../../include/ircd_events.h \ ../../config.h ../../include/ircd_handler.h ../../include/res.h \ - ../../include/capab.h ../../include/ircd_log.h ../../include/s_debug.h + ../../include/capab.h ../../include/ircd_features.h \ + ../../include/ircd_log.h ../../include/s_debug.h From f834d955a5e01b59bf1402990abcea0bc57a9430 Mon Sep 17 00:00:00 2001 From: MrIron Date: Sat, 18 Oct 2025 21:21:50 +0200 Subject: [PATCH 07/13] Better handling of ircu relevant netconfig options. --- include/ircd_netconf.h | 11 ++- ircd/ircd_netconf.c | 187 ++++++++++++++++++++++++++++++----------- 2 files changed, 146 insertions(+), 52 deletions(-) diff --git a/include/ircd_netconf.h b/include/ircd_netconf.h index 7ea59d3c..c23967d2 100644 --- a/include/ircd_netconf.h +++ b/include/ircd_netconf.h @@ -52,6 +52,12 @@ struct ConfigCallback { struct ConfigCallback *next; /**< Next callback */ }; +/** Network configuration options */ +enum NetConf { + /* To be included. This is the implementation only. */ + NETCONF_LAST_NC +}; + /* * Prototypes */ @@ -62,5 +68,8 @@ extern void config_register_callback(const char *key_prefix, config_callback_f c extern void config_unregister_callback(const char *key_prefix); extern void config_burst(struct Client *cptr); extern void config_stats(struct Client *sptr, const struct StatDesc *sd, char *param); +extern int netconf_int(enum NetConf key); +extern int netconf_bool(enum NetConf key); +extern const char *netconf_str(enum NetConf key); -#endif /* INCLUDED_ircd_config_h */ \ No newline at end of file +#endif /* INCLUDED_ircd_netconf_h */ diff --git a/ircd/ircd_netconf.c b/ircd/ircd_netconf.c index a08ad2d3..6415b5f6 100644 --- a/ircd/ircd_netconf.c +++ b/ircd/ircd_netconf.c @@ -43,6 +43,37 @@ static struct ConfigEntry *config_list = NULL; /** Head of the callback list */ static struct ConfigCallback *callback_list = NULL; +#define NETCONF_INT 0x0001 /**< set if entry contains an integer value */ +#define NETCONF_BOOL 0x0002 /**< set if entry contains a boolean value */ +#define NETCONF_STR 0x0003 /**< set if entry contains a string value */ +#define NETCONF_MASK 0x000f /**< possible value types */ + +/** Declare a network configuration option that takes integer values. */ +#define NC_I(type, cf_string, v_int) \ + { NETCONF_ ## type, cf_string, NETCONF_INT, 0, (v_int), 0, 0 } + +/** Declare a network configuration option that takes boolean values. */ +#define NC_B(type, cf_string, v_int) \ + { NETCONF_ ## type, cf_string, NETCONF_BOOL, 0, (v_int), 0, 0 } + +/** Declare a network configuration option that takes string values. */ +#define NC_S(type, cf_string, v_str) \ + { NETCONF_ ## type, cf_string, NETCONF_STR, 0, 0, 0, (v_str) } + +/** Network configuration description structure */ +static struct NetConfDesc { + enum NetConf netconf; /**< configuration identifier */ + char* type; /**< string describing type */ + unsigned int flags; /**< flags for configuration */ + int v_int; /**< integer value */ + int def_int; /**< default integer value */ + char* v_str; /**< string value */ + char* def_str; /**< default string value */ +} netconf_descs[] = { + + { NETCONF_LAST_NC, 0, 0, 0, 0, 0, 0 } /* sentinel */ +}; + /** Find a configuration entry by key * @param[in] key Configuration key to find * @return Configuration entry or NULL if not found @@ -50,14 +81,14 @@ static struct ConfigCallback *callback_list = NULL; static struct ConfigEntry *config_find(const char *key) { struct ConfigEntry *entry; - + assert(key != NULL); - + for (entry = config_list; entry; entry = entry->next) { if (ircd_strcmp(entry->key, key) == 0) return entry; } - + return NULL; } @@ -69,7 +100,7 @@ static struct ConfigEntry *config_find(const char *key) static void config_call_callbacks(const char *key, const char *old_value, const char *new_value) { struct ConfigCallback *cb; - + for (cb = callback_list; cb; cb = cb->next) { if (ircd_strncmp(key, cb->key_prefix, strlen(cb->key_prefix)) == 0) { cb->callback(key, old_value, new_value); @@ -79,7 +110,7 @@ static void config_call_callbacks(const char *key, const char *old_value, const /** Set a configuration option * @param[in] key Configuration key - * @param[in] value Configuration value + * @param[in] value Configuration value * @param[in] timestamp Timestamp when this config was set * @return 1 if the value was updated, 0 if it was created, -1 on error */ @@ -88,28 +119,28 @@ int config_set(const char *key, const char *value, time_t timestamp) struct ConfigEntry *entry; char *old_value = NULL; int result; - + assert(key != NULL); assert(value != NULL); - + entry = config_find(key); - + if (entry) { /* Only update if timestamp is newer */ if (timestamp <= entry->timestamp) return CONFIG_REJECTED; - + /* Save old value for callbacks */ DupString(old_value, entry->value); - + /* Check if value actually changed */ int value_changed = (ircd_strcmp(old_value, value) != 0); - + /* Update existing entry */ MyFree(entry->value); DupString(entry->value, value); entry->timestamp = timestamp; - + result = value_changed ? CONFIG_CHANGED : CONFIG_TIMESTAMP; } else { /* Create new entry */ @@ -121,18 +152,18 @@ int config_set(const char *key, const char *value, time_t timestamp) config_list = entry; result = CONFIG_CREATED; } - - Debug((DEBUG_DEBUG, "Config %s: %s = %s (timestamp: %lu)", - (result == CONFIG_CHANGED) ? "changed" : - (result == CONFIG_TIMESTAMP) ? "timestamp updated" : "set", + + Debug((DEBUG_DEBUG, "Config %s: %s = %s (timestamp: %lu)", + (result == CONFIG_CHANGED) ? "changed" : + (result == CONFIG_TIMESTAMP) ? "timestamp updated" : "set", key, value, (unsigned long)timestamp)); - + /* Call callbacks */ config_call_callbacks(key, old_value, value); - + if (old_value) MyFree(old_value); - + return result; } @@ -143,25 +174,11 @@ int config_set(const char *key, const char *value, time_t timestamp) const char *config_get(const char *key) { struct ConfigEntry *entry; - - assert(key != NULL); - - entry = config_find(key); - return entry ? entry->value : NULL; -} -/** Get the timestamp of a configuration option - * @param[in] key Configuration key - * @return Timestamp or 0 if not found - */ -time_t config_get_timestamp(const char *key) -{ - struct ConfigEntry *entry; - assert(key != NULL); - + entry = config_find(key); - return entry ? entry->timestamp : 0; + return entry ? entry->value : NULL; } /** Count the number of configuration entries @@ -171,10 +188,10 @@ static int config_count(void) { struct ConfigEntry *entry; int count = 0; - + for (entry = config_list; entry; entry = entry->next) count++; - + return count; } @@ -185,10 +202,10 @@ static int config_count(void) void config_register_callback(const char *key_prefix, config_callback_f callback) { struct ConfigCallback *cb; - + assert(key_prefix != NULL); assert(callback != NULL); - + /* Check if callback already exists */ for (cb = callback_list; cb; cb = cb->next) { if (ircd_strcmp(cb->key_prefix, key_prefix) == 0) { @@ -196,36 +213,36 @@ void config_register_callback(const char *key_prefix, config_callback_f callback return; } } - + /* Create new callback */ cb = MyMalloc(sizeof(struct ConfigCallback)); DupString(cb->key_prefix, key_prefix); cb->callback = callback; cb->next = callback_list; callback_list = cb; - + Debug((DEBUG_DEBUG, "Config callback registered for prefix: %s", key_prefix)); } -/** Unregister a callback for configuration changes +/** Unregister a callback for configuration changes * @param[in] key_prefix Key prefix that was registered */ void config_unregister_callback(const char *key_prefix) { struct ConfigCallback *cb, *prev = NULL; - + assert(key_prefix != NULL); - + for (cb = callback_list; cb; prev = cb, cb = cb->next) { if (ircd_strcmp(cb->key_prefix, key_prefix) == 0) { if (prev) prev->next = cb->next; else callback_list = cb->next; - + MyFree(cb->key_prefix); MyFree(cb); - + Debug((DEBUG_DEBUG, "Config callback unregistered for prefix: %s", key_prefix)); return; } @@ -238,13 +255,13 @@ void config_unregister_callback(const char *key_prefix) void config_burst(struct Client *cptr) { struct ConfigEntry *entry; - + for (entry = config_list; entry; entry = entry->next) { sendcmdto_one(&me, CMD_CONFIG, cptr, "%Tu %s %s", entry->timestamp, entry->key, entry->value); } - - Debug((DEBUG_INFO, "Config burst: %d entries sent to %s", + + Debug((DEBUG_INFO, "Config burst: %d entries sent to %s", config_count(), cli_name(cptr))); } @@ -256,10 +273,78 @@ void config_burst(struct Client *cptr) void config_stats(struct Client *sptr, const struct StatDesc *sd, char *param) { struct ConfigEntry *entry; - + for (entry = config_list; entry; entry = entry->next) { send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, "%Tu %s :%s", entry->timestamp, entry->key, entry->value); } -} \ No newline at end of file +} + +/** Find a netconf description by key + * @param[in] key NetConf enum key + * @return NetConf description or NULL if not found + */ +static struct NetConfDesc *netconf_find(enum NetConf key) +{ + int i; + + for (i = 0; netconf_descs[i].netconf != NETCONF_LAST_NC; i++) { + if (netconf_descs[i].netconf == key) + return &netconf_descs[i]; + } + + return NULL; +} + +/** Get integer value of a configuration option with default + * @param[in] key NetConf enum key + * @return Integer value (from config or default) + */ +int netconf_int(enum NetConf key) +{ + struct NetConfDesc *desc = netconf_find(key); + const char *value; + + assert(desc != NULL); + assert((desc->flags & NETCONF_MASK) == NETCONF_INT); + + value = config_get(desc->type); + return value ? atoi(value) : desc->def_int; +} + +/** Get boolean value of a configuration option with default + * @param[in] key NetConf enum key + * @return Boolean value (0 or 1, from config or default) + */ +int netconf_bool(enum NetConf key) +{ + struct NetConfDesc *desc = netconf_find(key); + const char *value; + + assert(desc != NULL); + assert((desc->flags & NETCONF_MASK) == NETCONF_BOOL); + + value = config_get(desc->type); + if (!value) return desc->def_int; + + return (ircd_strcmp(value, "true") == 0 || + ircd_strcmp(value, "1") == 0 || + ircd_strcmp(value, "yes") == 0) ? 1 : 0; +} + +/** Get string value of a configuration option with default + * @param[in] key NetConf enum key + * @return String value (from config or default) + */ +const char *netconf_str(enum NetConf key) +{ + struct NetConfDesc *desc = netconf_find(key); + const char *value; + + assert(desc != NULL); + assert((desc->flags & NETCONF_MASK) == NETCONF_STR); + + value = config_get(desc->type); + return value ? value : desc->def_str; +} From 784fcfb9c330cd98883967509f11fbee2aa2f2c3 Mon Sep 17 00:00:00 2001 From: MrIron Date: Sat, 18 Oct 2025 23:29:12 +0200 Subject: [PATCH 08/13] Added support for CAP LS 302 (incl. CAP NEW/DEL and cap-notify). Added support for SASL authentication. --- include/ircd_features.h | 1 - include/ircd_netconf.h | 6 +++- include/sasl.h | 2 -- ircd/Makefile.in | 71 +++++++++++++++++++++++++---------------- ircd/ircd.c | 1 - ircd/ircd_netconf.c | 4 +++ ircd/m_sasl.c | 18 +++-------- ircd/s_serv.c | 1 - ircd/sasl.c | 27 +++------------- 9 files changed, 63 insertions(+), 68 deletions(-) diff --git a/include/ircd_features.h b/include/ircd_features.h index 829ee530..67f3feb3 100644 --- a/include/ircd_features.h +++ b/include/ircd_features.h @@ -122,7 +122,6 @@ enum Feature { FEAT_HIS_LINKS, FEAT_HIS_TRACE, FEAT_HIS_STATS_a, - FEAT_HIS_STATS_C, FEAT_HIS_STATS_c, FEAT_HIS_STATS_C, FEAT_HIS_STATS_d, diff --git a/include/ircd_netconf.h b/include/ircd_netconf.h index c23967d2..b938e4e9 100644 --- a/include/ircd_netconf.h +++ b/include/ircd_netconf.h @@ -54,7 +54,11 @@ struct ConfigCallback { /** Network configuration options */ enum NetConf { - /* To be included. This is the implementation only. */ + /* SASL configuration options */ + NETCONF_SASL_SERVER, + NETCONF_SASL_MECHANISMS, + NETCONF_SASL_TIMEOUT, + NETCONF_LAST_NC }; diff --git a/include/sasl.h b/include/sasl.h index 66b79497..036f6f82 100644 --- a/include/sasl.h +++ b/include/sasl.h @@ -30,8 +30,6 @@ struct StatDesc; /* Public SASL functions */ extern void sasl_init(void); extern int sasl_available(void); -extern const char* sasl_get_server(void); -extern const char* sasl_get_mechanisms(void); extern int sasl_mechanism_supported(const char* mechanism); extern void sasl_check_capability(void); extern void sasl_send_xreply(struct Client* sptr, const char* routing, const char* reply); diff --git a/ircd/Makefile.in b/ircd/Makefile.in index 4032823d..a2db8e5b 100644 --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -97,13 +97,12 @@ IRCD_SRC = \ hash.c \ ircd.c \ ircd_alloc.c \ - ircd_config.c \ + ircd_netconf.c \ ircd_crypt.c \ ircd_events.c \ ircd_features.c \ ircd_lexer.c \ ircd_log.c \ - ircd_netconf.c \ ircd_relay.c \ ircd_reply.c \ ircd_res.c \ @@ -168,7 +167,6 @@ IRCD_SRC = \ m_rping.c \ m_rpong.c \ m_sasl.c \ - m_config.c \ m_server.c \ m_set.c \ m_settime.c \ @@ -453,12 +451,20 @@ ircd.o: ircd.c ../config.h ../include/ircd.h ../include/struct.h \ ../include/numeric.h ../include/numnicks.h ../include/opercmds.h \ ../include/parse.h ../include/res.h ../include/s_auth.h \ ../include/s_bsd.h ../include/s_conf.h ../include/s_debug.h \ - ../include/s_misc.h ../include/s_stats.h ../include/send.h \ - ../include/sys.h ../include/uping.h ../include/userload.h \ - ../include/version.h ../include/whowas.h + ../include/s_misc.h ../include/s_stats.h ../include/sasl.h \ + ../include/send.h ../include/sys.h ../include/uping.h \ + ../include/userload.h ../include/version.h ../include/whowas.h ircd_alloc.o: ircd_alloc.c ../config.h ../include/ircd_alloc.h \ ../include/ircd_log.h ../include/ircd_string.h ../include/ircd_chattr.h \ ../include/s_debug.h ../include/ircd_defs.h +ircd_netconf.o: ircd_netconf.c ../config.h ../include/client.h \ + ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_netconf.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_debug.h ../include/send.h ircd_crypt.o: ircd_crypt.c ../config.h ../include/ircd_crypt.h \ ../include/ircd_alloc.h ../include/ircd_features.h ../include/ircd_log.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/s_debug.h \ @@ -496,14 +502,6 @@ ircd_log.o: ircd_log.c ../config.h ../include/ircd_log.h \ ../include/ircd_chattr.h ../include/ircd.h ../include/struct.h \ ../include/numeric.h ../include/s_debug.h ../include/send.h \ ../include/struct.h -ircd_netconf.o: ircd_netconf.c ../config.h ../include/client.h \ - ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ - ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_netconf.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_debug.h ../include/send.h ircd_relay.o: ircd_relay.c ../config.h ../include/ircd_relay.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ @@ -633,7 +631,7 @@ m_cap.o: m_cap.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/ircd_chattr.h ../include/ircd_log.h ../include/ircd_reply.h \ ../include/ircd_snprintf.h ../include/ircd_string.h ../include/msg.h \ ../include/numeric.h ../include/send.h ../include/s_auth.h \ - ../include/s_user.h + ../include/s_user.h ../include/s_bsd.h m_clearmode.o: m_clearmode.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ @@ -654,10 +652,10 @@ m_config.o: m_config.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_netconf.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/send.h \ - ../include/s_debug.h + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_netconf.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/send.h ../include/s_debug.h m_connect.o: m_connect.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ @@ -721,8 +719,8 @@ m_endburst.o: m_endburst.c ../config.h ../include/channel.h \ ../include/ircd_handler.h ../include/capab.h ../include/ircd_features.h \ ../include/hash.h ../include/ircd.h ../include/struct.h \ ../include/ircd_log.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h + ../include/ircd_chattr.h ../include/sasl.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/send.h m_error.o: m_error.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ @@ -1029,6 +1027,15 @@ m_rpong.o: m_rpong.c ../config.h ../include/client.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/opercmds.h ../include/send.h +m_sasl.o: m_sasl.c ../config.h ../include/client.h ../include/ircd_defs.h \ + ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ + ../include/ircd_handler.h ../include/res.h ../include/capab.h \ + ../include/ircd_features.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_events.h ../include/ircd_log.h ../include/ircd_netconf.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/sasl.h ../include/send.h \ + ../include/s_debug.h m_server.o: m_server.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ @@ -1232,7 +1239,7 @@ m_xreply.o: m_xreply.c ../config.h ../include/client.h \ ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ ../include/numeric.h ../include/numnicks.h ../include/s_auth.h \ - ../include/send.h + ../include/send.h ../include/sasl.h match.o: match.c ../config.h ../include/match.h ../include/res.h \ ../include/ircd_chattr.h ../include/ircd_string.h \ ../include/ircd_snprintf.h @@ -1328,8 +1335,8 @@ s_bsd.o: s_bsd.c ../config.h ../include/s_bsd.h ../include/client.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ ../include/capab.h ../include/ircd_features.h ../include/IPcheck.h \ ../include/channel.h ../include/class.h ../include/client.h \ - ../include/hash.h ../include/ircd_alloc.h ../include/ircd_log.h \ - ../include/ircd_features.h ../include/ircd_osdep.h \ + ../include/hash.h ../include/ircd_alloc.h ../include/ircd_events.h \ + ../include/ircd_log.h ../include/ircd_features.h ../include/ircd_osdep.h \ ../include/ircd_reply.h ../include/ircd_snprintf.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/ircd.h \ ../include/struct.h ../include/list.h ../include/listener.h \ @@ -1384,7 +1391,7 @@ s_misc.o: s_misc.c ../config.h ../include/s_misc.h ../include/IPcheck.h \ ../include/s_conf.h ../include/client.h ../include/s_debug.h \ ../include/s_stats.h ../include/s_user.h ../include/send.h \ ../include/struct.h ../include/sys.h ../include/uping.h \ - ../include/userload.h + ../include/userload.h ../include/sasl.h s_numeric.o: s_numeric.c ../config.h ../include/s_numeric.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ @@ -1407,7 +1414,7 @@ s_serv.o: s_serv.c ../config.h ../include/s_serv.h ../include/IPcheck.h \ ../include/querycmds.h ../include/s_bsd.h ../include/s_conf.h \ ../include/client.h ../include/s_debug.h ../include/s_misc.h \ ../include/s_user.h ../include/send.h ../include/struct.h \ - ../include/sys.h ../include/userload.h + ../include/sys.h ../include/userload.h ../include/sasl.h s_stats.o: s_stats.c ../config.h ../include/class.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ @@ -1422,7 +1429,8 @@ s_stats.o: s_stats.c ../config.h ../include/class.h ../include/client.h \ ../include/res.h ../include/s_auth.h ../include/s_bsd.h \ ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \ ../include/s_serv.h ../include/s_stats.h ../include/s_user.h \ - ../include/send.h ../include/struct.h ../include/userload.h + ../include/sasl.h ../include/send.h ../include/struct.h \ + ../include/userload.h s_user.o: s_user.c ../config.h ../include/s_user.h ../include/IPcheck.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../include/class.h ../include/client.h ../include/dbuf.h \ @@ -1440,6 +1448,15 @@ s_user.o: s_user.c ../config.h ../include/s_user.h ../include/IPcheck.h \ ../include/struct.h ../include/supported.h ../include/channel.h \ ../include/sys.h ../include/userload.h ../include/version.h \ ../include/whowas.h ../include/handlers.h +sasl.o: sasl.c ../config.h ../include/sasl.h ../include/client.h \ + ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ + ../include/capab.h ../include/ircd_features.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/ircd_events.h \ + ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/ircd_reply.h ../include/ircd_netconf.h ../include/send.h \ + ../include/msg.h ../include/capab.h ../include/numnicks.h \ + ../include/s_debug.h ../include/s_bsd.h ../include/numeric.h send.o: send.c ../config.h ../include/send.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/res.h \ diff --git a/ircd/ircd.c b/ircd/ircd.c index 2c6d5d78..dedd5eb8 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -33,7 +33,6 @@ #include "ircd_alloc.h" #include "ircd_events.h" #include "ircd_features.h" -#include "ircd_config.h" #include "ircd_log.h" #include "ircd_reply.h" #include "ircd_signal.h" diff --git a/ircd/ircd_netconf.c b/ircd/ircd_netconf.c index 6415b5f6..648bbe92 100644 --- a/ircd/ircd_netconf.c +++ b/ircd/ircd_netconf.c @@ -70,6 +70,10 @@ static struct NetConfDesc { char* v_str; /**< string value */ char* def_str; /**< default string value */ } netconf_descs[] = { + /* SASL configuration options */ + NC_S(SASL_SERVER, "sasl.server", ""), + NC_S(SASL_MECHANISMS, "sasl.mechanisms", ""), + NC_I(SASL_TIMEOUT, "sasl.timeout", 30), { NETCONF_LAST_NC, 0, 0, 0, 0, 0, 0 } /* sentinel */ }; diff --git a/ircd/m_sasl.c b/ircd/m_sasl.c index d937ae40..50efb1bd 100644 --- a/ircd/m_sasl.c +++ b/ircd/m_sasl.c @@ -81,9 +81,9 @@ #include "client.h" #include "ircd.h" -#include "ircd_config.h" #include "ircd_events.h" #include "ircd_log.h" +#include "ircd_netconf.h" #include "ircd_reply.h" #include "ircd_string.h" #include "msg.h" @@ -138,14 +138,6 @@ static void sasl_start_timeout(struct Client* cptr) assert(MyConnect(cptr)); assert(cli_sasl(cptr) != 0); /* Should have active SASL session */ - /* Get configured timeout */ - timeout_str = config_get("sasl.timeout"); - if (timeout_str) { - timeout_seconds = atoi(timeout_str); - if (timeout_seconds <= 0) - timeout_seconds = 60; - } - timer = cli_sasl_timer(cptr); /* Timer should not already be active */ @@ -153,10 +145,10 @@ static void sasl_start_timeout(struct Client* cptr) /* Start timer */ timer_add(timer_init(timer), sasl_timeout_callback, (void*) cptr, - TT_RELATIVE, timeout_seconds); + TT_RELATIVE, netconf_int(NETCONF_SASL_TIMEOUT)); Debug((DEBUG_INFO, "SASL timeout started for client %s (%d seconds)", - cli_name(cptr), timeout_seconds)); + cli_name(cptr), netconf_int(NETCONF_SASL_TIMEOUT))); } /** Stop the SASL timeout timer for a client @@ -192,7 +184,7 @@ int m_sasl(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) if (HasFlag(sptr, FLAG_SASL) || HasFlag(sptr, FLAG_ACCOUNT)) return send_reply(cptr, ERR_SASLALREADY); - acptr = find_match_server((char*)sasl_get_server()); + acptr = find_match_server((char*)netconf_str(NETCONF_SASL_SERVER)); if (!sasl_available() || !acptr) return send_reply(cptr, ERR_SASLFAIL, "The login server is currently disconnected. Please excuse the inconvenience."); @@ -212,7 +204,7 @@ int m_sasl(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) /* Is this the initial authentication challenge? */ if (!cli_sasl(cptr)) { if (!sasl_mechanism_supported(parv[1])) - return send_reply(cptr, RPL_SASLMECHS, sasl_get_mechanisms()); + return send_reply(cptr, RPL_SASLMECHS, netconf_str(NETCONF_SASL_MECHANISMS)); cli_sasl(cptr) = ++routing_ticker; diff --git a/ircd/s_serv.c b/ircd/s_serv.c index 9fb79713..f0563425 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -34,7 +34,6 @@ #include "hash.h" #include "ircd.h" #include "ircd_alloc.h" -#include "ircd_config.h" #include "ircd_log.h" #include "ircd_netconf.h" #include "ircd_reply.h" diff --git a/ircd/sasl.c b/ircd/sasl.c index a45a1b69..d5cbc19c 100644 --- a/ircd/sasl.c +++ b/ircd/sasl.c @@ -30,10 +30,10 @@ #include "client.h" #include "ircd.h" #include "ircd_alloc.h" -#include "ircd_config.h" #include "ircd_events.h" #include "ircd_string.h" #include "ircd_reply.h" +#include "ircd_netconf.h" #include "send.h" #include "msg.h" #include "capab.h" @@ -58,31 +58,14 @@ static struct SaslStats sasl_statistics = { 0, 0 }; */ int sasl_available(void) { - const char* server = config_get("sasl.server"); - const char* mechanisms = config_get("sasl.mechanisms"); - - if (!server || !mechanisms || !find_match_server((char*)server)) + if (!*netconf_str(NETCONF_SASL_SERVER) + || !*netconf_str(NETCONF_SASL_MECHANISMS) + || !find_match_server((char*)netconf_str(NETCONF_SASL_SERVER))) return 0; return 1; } -/** Get the current SASL server name - * @return Server name or NULL if none set - */ -const char* sasl_get_server(void) -{ - return config_get("sasl.server"); -} - -/** Get the current SASL mechanisms - * @return Comma-delimited mechanism list or NULL if none set - */ -const char* sasl_get_mechanisms(void) -{ - return config_get("sasl.mechanisms"); -} - /** Check if a mechanism exists in a mechanism list * @param[in] mechanism The mechanism to find * @param[in] mechanism_list Comma-delimited list of mechanisms @@ -125,7 +108,7 @@ static int mechanism_in_list(const char* mechanism, const char* mechanism_list) */ int sasl_mechanism_supported(const char* mechanism) { - return mechanism_in_list(mechanism, config_get("sasl.mechanisms")); + return mechanism_in_list(mechanism, netconf_str(NETCONF_SASL_MECHANISMS)); } /** Check and update SASL capability availability From 35cafe9936ddb1af1818598b63bea8a42eb99933 Mon Sep 17 00:00:00 2001 From: MrIron Date: Sat, 18 Oct 2025 23:54:27 +0200 Subject: [PATCH 09/13] Duplication fix and stats clean-up. --- ircd/ircd_features.c | 1 - ircd/sasl.c | 16 +++++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/ircd/ircd_features.c b/ircd/ircd_features.c index 47e13e5e..98ccce8c 100644 --- a/ircd/ircd_features.c +++ b/ircd/ircd_features.c @@ -387,7 +387,6 @@ static struct FeatureDesc { F_B(HIS_LINKS, 0, 1, 0), F_B(HIS_TRACE, 0, 1, 0), F_B(HIS_STATS_a, 0, 1, 0), - F_B(HIS_STATS_C, 0, 1, 0), F_B(HIS_STATS_c, 0, 1, 0), F_B(HIS_STATS_C, 0, 1, 0), F_B(HIS_STATS_d, 0, 1, 0), diff --git a/ircd/sasl.c b/ircd/sasl.c index d5cbc19c..f33fc450 100644 --- a/ircd/sasl.c +++ b/ircd/sasl.c @@ -281,25 +281,19 @@ void sasl_send_xreply(struct Client* sptr, const char* routing, const char* repl */ void sasl_stats(struct Client* sptr, const struct StatDesc* sd, char* param) { - const char* server = config_get("sasl.server"); - const char* mechanisms = config_get("sasl.mechanisms"); - const char* timeout = config_get("sasl.timeout"); - - if (server && mechanisms) { + if (sasl_available()) { send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, - ":SASL server: %s", server); + ":SASL server: %s", netconf_str(NETCONF_SASL_SERVER)); send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, - ":SASL mechanisms: %s", mechanisms); + ":SASL mechanisms: %s", netconf_str(NETCONF_SASL_MECHANISMS)); send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, - ":SASL timeout: %s", timeout); + ":SASL timeout: %d", netconf_int(NETCONF_SASL_TIMEOUT)); send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, ":SASL successful auths: %lu", sasl_statistics.auth_success); send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, ":SASL failed auths: %lu", sasl_statistics.auth_failed); - send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, - ":SASL available: %s", sasl_available() ? "Yes" : "No"); } else { send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG, - ":SASL not configured"); + ":SASL not available"); } } \ No newline at end of file From db0cec08af2f480f7bbebcee12dc73e8e29089c1 Mon Sep 17 00:00:00 2001 From: MrIron Date: Wed, 22 Oct 2025 09:41:15 +0200 Subject: [PATCH 10/13] Pass account onto iauth for sasl authentication during registration. Make the iauth session not terminate until after capability negotiations. --- include/s_auth.h | 1 + ircd/s_auth.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++- ircd/sasl.c | 33 ++------------------------------ 3 files changed, 51 insertions(+), 32 deletions(-) diff --git a/include/s_auth.h b/include/s_auth.h index 657e925a..fd6e7cbe 100644 --- a/include/s_auth.h +++ b/include/s_auth.h @@ -39,6 +39,7 @@ extern int auth_set_pong(struct AuthRequest *auth, unsigned int cookie); extern int auth_set_user(struct AuthRequest *auth, const char *username, const char *hostname, const char *servername, const char *userinfo); extern int auth_set_nick(struct AuthRequest *auth, const char *nickname); extern int auth_set_password(struct AuthRequest *auth, const char *password); +extern int auth_set_account(struct AuthRequest *auth, const char *account_info); extern int auth_cap_start(struct AuthRequest *auth); extern int auth_cap_done(struct AuthRequest *auth); extern int auth_spoof_user(struct AuthRequest *auth, const char *username, const char *hostname, const char *ip); diff --git a/ircd/s_auth.c b/ircd/s_auth.c index 473ef46f..0d78a547 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -363,6 +363,50 @@ static int auth_set_username(struct AuthRequest *auth) return exit_client(sptr, sptr, &me, "USER: Bad username"); } +/** Set account for user associated with \a auth. + * @param[in] auth Authorization request for client. + */ +int auth_set_account(struct AuthRequest *auth, const char *account_info) +{ + assert(auth != NULL); + + struct Client *sptr = auth->client; + char *account_copy = NULL, *account = NULL, *id_str = NULL, *flags_str = NULL, *extra = NULL; + + /* Parse account information: username:id:flags */ + DupString(account_copy, account_info); + if (!account_copy) + return 1; + + account = strtok(account_copy, ":"); + id_str = strtok(NULL, ":"); + flags_str = strtok(NULL, " "); + extra = strtok(NULL, ""); + + /* Copy account name to User structure */ + ircd_strncpy(cli_user(sptr)->account, account, ACCOUNTLEN); + + /* Parse account ID if provided */ + if (id_str) { + cli_user(sptr)->acc_id = strtoul(id_str, NULL, 10); + } + + if (flags_str) { + cli_user(sptr)->acc_flags = strtoul(flags_str, NULL, 10); + } + + SetAccount(sptr); + + /* Check for +x flag (host hiding) */ + if (extra && strstr(extra, "+x") && feature_bool(FEAT_HOST_HIDING)) { + SetHiddenHost(sptr); + } + + sendto_iauth(sptr, "A %s", cli_user(sptr)->account); + MyFree(account_copy); + return 0; +} + /** Notifies IAuth of a status change for the client. * * @param[in] auth Authorization request that was updated. @@ -399,7 +443,8 @@ static void iauth_notify(struct AuthRequest *auth, enum AuthRequestFlag flag) break; case AR_IAUTH_PENDING: - sendto_iauth(sptr, "T"); + if (!FlagHas(&auth->flags, AR_CAP_PENDING)) + sendto_iauth(sptr, "T"); break; default: @@ -1296,6 +1341,7 @@ int auth_cap_start(struct AuthRequest *auth) { assert(auth != NULL); FlagSet(&auth->flags, AR_CAP_PENDING); + sendto_iauth(auth->client, "c"); return 0; } @@ -1307,6 +1353,7 @@ int auth_cap_start(struct AuthRequest *auth) int auth_cap_done(struct AuthRequest *auth) { assert(auth != NULL); + sendto_iauth(auth->client, "e"); return check_auth_finished(auth, AR_CAP_PENDING); } diff --git a/ircd/sasl.c b/ircd/sasl.c index f33fc450..6863a459 100644 --- a/ircd/sasl.c +++ b/ircd/sasl.c @@ -38,6 +38,7 @@ #include "msg.h" #include "capab.h" #include "numnicks.h" +#include "s_auth.h" #include "s_debug.h" #include "s_bsd.h" #include "numeric.h" @@ -208,37 +209,7 @@ void sasl_send_xreply(struct Client* sptr, const char* routing, const char* repl * If this is a SASL authentication after registration, the username will be set by the service using AC. */ if (!IsUser(cli)) { - /* Parse account information: username:id:flags */ - DupString(account_copy, account_info); - if (!account_copy) - return; - - username = strtok(account_copy, ":"); - id_str = strtok(NULL, ":"); - flags_str = strtok(NULL, " "); - extra = strtok(NULL, ""); - - /* Copy account name to User structure */ - ircd_strncpy(cli_user(cli)->account, username, ACCOUNTLEN); - - /* Parse account ID if provided */ - if (id_str) { - cli_user(cli)->acc_id = strtoul(id_str, NULL, 10); - } - - /* Parse account flags if provided */ - if (flags_str) { - cli_user(cli)->acc_flags = strtoul(flags_str, NULL, 10); - } - - SetAccount(cli); - - /* Check for +x flag (host hiding) */ - if (extra && strstr(extra, "+x") && feature_bool(FEAT_HOST_HIDING)) { - SetHiddenHost(cli); - } - - MyFree(account_copy); + auth_set_account(cli_auth(cli), account_info); /** * For already registered users, we send RPL_LOGGEDIN. For non-registered users, From 316f9790d5bdd85e3202501eb686ac9122e9fa25 Mon Sep 17 00:00:00 2001 From: MrIron Date: Wed, 22 Oct 2025 11:06:20 +0200 Subject: [PATCH 11/13] Kill connections also having soft_done --- ircd/s_auth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ircd/s_auth.c b/ircd/s_auth.c index 0d78a547..e844b2fa 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -966,8 +966,7 @@ int auth_ping_timeout(struct Client *cptr) /* Check for iauth timeout. */ if (FlagHas(&auth->flags, AR_IAUTH_PENDING)) { - if (IAuthHas(iauth, IAUTH_REQUIRED) - && !FlagHas(&auth->flags, AR_IAUTH_SOFT_DONE)) { + if (IAuthHas(iauth, IAUTH_REQUIRED)) { sendheader(cptr, REPORT_FAIL_IAUTH); return exit_client_msg(cptr, cptr, &me, "Authorization Timeout"); } From 412f263efa98608f88a01972a055b79553f8ed1b Mon Sep 17 00:00:00 2001 From: MrIron Date: Thu, 23 Oct 2025 11:18:58 +0200 Subject: [PATCH 12/13] fix: Use correct username. --- ircd/s_auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ircd/s_auth.c b/ircd/s_auth.c index e844b2fa..6d75ed98 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -611,7 +611,7 @@ static int check_auth_finished(struct AuthRequest *auth, int bitclr) { if (HasFlag(auth->client, FLAG_SASL)) { send_reply(auth->client, RPL_LOGGEDIN, - cli_name(auth->client), cli_username(auth->client), + cli_name(auth->client), cli_user(auth->client)->username, cli_user(auth->client)->host, cli_user(auth->client)->account, cli_user(auth->client)->account); } From 0deada50d064b6c829ce94a33db3bc18050e17cc Mon Sep 17 00:00:00 2001 From: MrIron Date: Fri, 24 Oct 2025 22:19:58 +0200 Subject: [PATCH 13/13] We only send cap start once to IAuth --- ircd/s_auth.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ircd/s_auth.c b/ircd/s_auth.c index 6d75ed98..ed45b255 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -1339,8 +1339,10 @@ void auth_send_xreply(struct Client *sptr, const char *routing, int auth_cap_start(struct AuthRequest *auth) { assert(auth != NULL); - FlagSet(&auth->flags, AR_CAP_PENDING); - sendto_iauth(auth->client, "c"); + if (!FlagHas(&auth->flags, AR_CAP_PENDING)) { + FlagSet(&auth->flags, AR_CAP_PENDING); + sendto_iauth(auth->client, "c"); + } return 0; }