This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Undernet IRC Server Source Code.".
The branch, u2_10_12_branch has been updated
via 0ff825c5595bd32fe578f3af5752d74b2134a3e2 (commit)
via 6ca205f7dba1371de1bf402ff684be95f31da5ae (commit)
via 6b6112a74c4b36377f6b5142346ecd2c21021927 (commit)
from 3352dc90498bd68b775f9b3de2ad48bb7d17ddfa (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 0ff825c5595bd32fe578f3af5752d74b2134a3e2
Author: Michael Poole <[email protected]>
Date: Sun Sep 12 15:16:44 2021 -0400
Only gripe about unhashed but named users
If a client disconnects before they have a nickname, hRemClient() is
expected to fail for them.
diff --git a/ircd/s_misc.c b/ircd/s_misc.c
index 08236447..a6a0cff3 100644
--- a/ircd/s_misc.c
+++ b/ircd/s_misc.c
@@ -279,7 +279,7 @@ static void exit_one_client(struct Client* bcptr, const
char* comment)
/* Remove bcptr from the client list */
#ifdef DEBUGMODE
- if (hRemClient(bcptr) != 0)
+ if (hRemClient(bcptr) != 0 && cli_name(bcptr)[0])
Debug((DEBUG_ERROR, "%p !in tab %s[%s] %p %p %p %d %d %p",
bcptr, cli_name(bcptr), cli_from(bcptr) ?
cli_sockhost(cli_from(bcptr)) : "??host",
cli_from(bcptr), cli_next(bcptr), cli_prev(bcptr), cli_fd(bcptr),
commit 6ca205f7dba1371de1bf402ff684be95f31da5ae
Author: Michael Poole <[email protected]>
Date: Sun Sep 12 15:15:58 2021 -0400
Allow exceptions from IPcheck's connect-rate limits
diff --git a/doc/example.conf b/doc/example.conf
index ac95227f..131bfbf7 100644
--- a/doc/example.conf
+++ b/doc/example.conf
@@ -824,6 +824,18 @@ WebIRC {
hidden = yes; # hides IP in /stats webirc
};
+# The IPCheck block can be used to exempt IP addresses or netblocks from
+# the connection rate-limiting code that gives messages like:
+# "Your host is trying to (re)connect too fast -- throttled"
+#
+# Note that exceptions ONLY work with unresolved addresses, not resolved
+# hostnames. Also, loopback addresses -- even for IPv4 -- are compared
+# against the IPv6 localhost address, ::1. If you want to exempt
+# 127.0.0.1 from checks, write "::1" as an except address.
+IPCheck {
+ except "::1";
+}
+
# [features]
# IRC servers have a large number of options and features. Most of these
# are set at compile time through the use of #define's--see "make config"
diff --git a/include/IPcheck.h b/include/IPcheck.h
index 91693ac0..9a1d50fc 100644
--- a/include/IPcheck.h
+++ b/include/IPcheck.h
@@ -17,6 +17,8 @@ struct irc_in_addr;
* Prototypes
*/
extern void IPcheck_init(void);
+extern void IPcheck_clear_config(void);
+extern int IPcheck_except(const char *ip_mask);
extern int IPcheck_local_connect(const struct irc_in_addr *ip, time_t
*next_target_out);
extern void IPcheck_connect_fail(const struct Client *cptr, int disconnect);
extern void IPcheck_connect_succeeded(struct Client *cptr);
diff --git a/ircd/IPcheck.c b/ircd/IPcheck.c
index 80185ff2..6a75f8bb 100644
--- a/ircd/IPcheck.c
+++ b/ircd/IPcheck.c
@@ -23,6 +23,7 @@
#include "config.h"
#include "IPcheck.h"
+#include "channel.h" /* struct Ban */
#include "client.h"
#include "ircd.h"
#include "match.h"
@@ -32,6 +33,7 @@
#include "ircd_features.h"
#include "ircd_log.h"
#include "ircd_string.h" /* ircd_ntoa */
+#include "res.h" /* irc_in_addr_is_ipv4 */
#include "s_debug.h" /* Debug */
#include "s_user.h" /* TARGET_DELAY */
#include "send.h"
@@ -91,6 +93,10 @@ static struct IPRegistryEntry* freeList;
static struct IPRegistry48* freeList48;
/** Periodic timer to look for too-old registry entries. */
static struct Timer expireTimer;
+/** List of IPv4 net blocks exempt from IPcheck. */
+static struct Ban *exceptIPv4;
+/** List of IPv6 net blocks exempt from IPcheck. */
+static struct Ban *exceptIPv6;
/** Convert IP addresses to canonical form for comparison. IPv4
* addresses are translated into 6to4 form; IPv6 addresses are
@@ -351,6 +357,75 @@ void IPcheck_init(void)
timer_add(timer_init(&expireTimer), ip_registry_expire, 0, TT_PERIODIC, 60);
}
+/** Reset IPcheck configurable settings. */
+void IPcheck_clear_config(void)
+{
+ struct Ban *except;
+
+ /* Free any existing IPv4 exceptions. */
+ while (exceptIPv4) {
+ except = exceptIPv4;
+ exceptIPv4 = except->next;
+ free(except);
+ }
+
+ /* Free any existing IPv6 exceptions. */
+ while (exceptIPv6) {
+ except = exceptIPv6;
+ exceptIPv6 = exceptIPv6->next;
+ free(except);
+ }
+}
+
+/** Add an IP netblock exemption to IPcheck.
+ *
+ * @param[in] ip_mask IP address, optionally in CIDR netblock form.
+ * @return Zero on success, non-zero on error.
+ */
+int IPcheck_except(const char *ip_mask)
+{
+ struct Ban *except, **p_list;
+
+ /* Parse the IP address. */
+ except = MyMalloc(sizeof(*except));
+ if (!ipmask_parse(ip_mask, &except->address, &except->addrbits)) {
+ MyFree(except);
+ return 1;
+ }
+ if (!irc_in_addr_valid(&except->address)) {
+ MyFree(except);
+ return 2;
+ }
+
+ /* Add it to the right list. */
+ p_list = irc_in_addr_is_ipv4(&except->address)
+ ? &exceptIPv4 : &exceptIPv6;
+ except->next = *p_list;
+ *p_list = except;
+ return 0;
+}
+
+/** Indicates whether an IP address is exempt from per-IP connection
+ * rate limits.
+ *
+ * @param[in] addr Address to look up.
+ * @return Non-zero if the IP address is exempt, zero if it should be
+ * checked for too many connections in a short time.
+ */
+static int ip_registry_is_exempt(const struct irc_in_addr *addr)
+{
+ struct Ban *list;
+
+ list = irc_in_addr_is_ipv4(addr) ? exceptIPv4 : exceptIPv6;
+ while (list) {
+ if (ipmask_check(addr, &list->address, list->addrbits)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/** Check whether a new connection from a local client should be allowed.
* A connection is rejected if someone from the "same" address (see
* ip_registry_find()) connects IPCHECK_CLONE_LIMIT times, each time
@@ -359,11 +434,16 @@ void IPcheck_init(void)
* @param[out] next_target_out Receives time to grant another free target.
* @return Non-zero if the connection is permitted, zero if denied.
*/
-int ip_registry_check_local(const struct irc_in_addr *addr, time_t*
next_target_out)
+static int ip_registry_check_local(const struct irc_in_addr *addr, time_t*
next_target_out)
{
- struct IPRegistryEntry* entry = ip_registry_find(addr);
+ struct IPRegistryEntry* entry;
unsigned int free_targets = STARTTARGETS;
+ if (ip_registry_is_exempt(addr)) {
+ return 1;
+ }
+
+ entry = ip_registry_find(addr);
if (!irc_in_addr_is_ipv4(addr)) {
struct IPRegistry48* entry_48 = ip_48_find(addr);
@@ -450,7 +530,7 @@ reject:
* @param[in] is_burst Non-zero if client was introduced during a burst.
* @return Non-zero if the client should be accepted, zero if they must be
killed.
*/
-int ip_registry_check_remote(struct Client* cptr, int is_burst)
+static int ip_registry_check_remote(struct Client* cptr, int is_burst)
{
struct IPRegistryEntry* entry;
@@ -463,6 +543,10 @@ int ip_registry_check_remote(struct Client* cptr, int
is_burst)
return 1;
}
+ if (ip_registry_is_exempt(&cli_ip(cptr))) {
+ return 1;
+ }
+
if (!irc_in_addr_is_ipv4(&cli_ip(cptr))) {
struct IPRegistry48* entry_48 = ip_48_find(&cli_ip(cptr));
if (CONNECTED_SINCE(entry_48->last_connect) > IPCHECK_48_CLONE_PERIOD)
@@ -509,7 +593,7 @@ int ip_registry_check_remote(struct Client* cptr, int
is_burst)
* @param[in] addr Address of rejected client.
* @param[in] disconnect If true, also count the client as disconnecting.
*/
-void ip_registry_connect_fail(const struct irc_in_addr *addr, int disconnect)
+static void ip_registry_connect_fail(const struct irc_in_addr *addr, int
disconnect)
{
struct IPRegistryEntry* entry = ip_registry_find(addr);
@@ -537,13 +621,14 @@ void ip_registry_connect_fail(const struct irc_in_addr
*addr, int disconnect)
* the entry.
* @param[in,out] cptr Client that has successfully connected.
*/
-void ip_registry_connect_succeeded(struct Client *cptr)
+static void ip_registry_connect_succeeded(struct Client *cptr)
{
const char* tr = "";
unsigned int free_targets = STARTTARGETS;
struct IPRegistryEntry* entry = ip_registry_find(&cli_ip(cptr));
- assert(entry);
+ if (!entry)
+ return;
if (entry->target) {
memcpy(cli_targets(cptr), entry->target->targets, MAXTARGETS);
free_targets = entry->target->count;
@@ -560,14 +645,15 @@ void ip_registry_connect_succeeded(struct Client *cptr)
* information for his IP registry entry.
* @param[in] cptr Client that has exited.
*/
-void ip_registry_disconnect(struct Client *cptr)
+static void ip_registry_disconnect(struct Client *cptr)
{
struct IPRegistryEntry* entry = ip_registry_find(&cli_ip(cptr));
if (!irc_in_addr_valid(&cli_ip(cptr))) {
Debug((DEBUG_DNS, "IPcheck noting dicconnect from invalid %s.",
ircd_ntoa(&cli_ip(cptr))));
return;
}
- assert(entry);
+ if (!entry)
+ return;
assert(entry->connected > 0);
Debug((DEBUG_DNS, "IPcheck noting disconnect from %s.",
ircd_ntoa(&entry->addr)));
/*
@@ -636,7 +722,7 @@ void ip_registry_disconnect(struct Client *cptr)
* @param[in] addr Address to look up.
* @return Number of clients known to be connected from that address.
*/
-int ip_registry_count(const struct irc_in_addr *addr)
+static int ip_registry_count(const struct irc_in_addr *addr)
{
struct IPRegistryEntry* entry = ip_registry_find(addr);
return (entry) ? entry->connected : 0;
diff --git a/ircd/ircd_lexer.l b/ircd/ircd_lexer.l
index 7201dd5e..20e1a369 100644
--- a/ircd/ircd_lexer.l
+++ b/ircd/ircd_lexer.l
@@ -106,6 +106,8 @@ static struct lexer_token {
TOKEN(PROGRAM),
TOKEN(DNS),
TOKEN(WEBIRC),
+ TOKEN(IPCHECK),
+ TOKEN(EXCEPT),
#undef TOKEN
{ "administrator", ADMIN },
{ "apass_opmode", TPRIV_APASS_OPMODE },
diff --git a/ircd/ircd_parser.y b/ircd/ircd_parser.y
index 9347e136..74630e66 100644
--- a/ircd/ircd_parser.y
+++ b/ircd/ircd_parser.y
@@ -30,6 +30,7 @@
#include "fileio.h"
#include "gline.h"
#include "hash.h"
+#include "IPcheck.h"
#include "ircd.h"
#include "ircd_alloc.h"
#include "ircd_chattr.h"
@@ -177,6 +178,8 @@ static void free_slist(struct SLink **link) {
%token TOK_IPV4 TOK_IPV6
%token DNS
%token WEBIRC
+%token IPCHECK
+%token EXCEPT
/* and now a lot of privileges... */
%token TPRIV_CHAN_LIMIT TPRIV_MODE_LCHAN TPRIV_DEOP_LCHAN TPRIV_WALK_LCHAN
%token TPRIV_LOCAL_KILL TPRIV_REHASH TPRIV_RESTART TPRIV_DIE
@@ -204,7 +207,7 @@ blocks: blocks block | block;
block: adminblock | generalblock | classblock | connectblock |
uworldblock | operblock | portblock | jupeblock | clientblock |
killblock | cruleblock | motdblock | featuresblock | quarantineblock |
- pseudoblock | iauthblock | webircblock | error ';';
+ pseudoblock | iauthblock | webircblock | ipcheckblock | error ';';
/* The timespec, sizespec and expr was ripped straight from
* ircd-hybrid-7. */
@@ -1227,3 +1230,23 @@ webircip: IP '=' QSTRING ';' { MyFree(ip); ip = $3; };
webircpass: PASS '=' QSTRING ';' { MyFree(pass); pass = $3; };
webircdesc: DESCRIPTION '=' QSTRING ';' { MyFree(name); name = $3; };
webirchidden: HIDDEN '=' YES ';' { flags = flags | 1; }
+
+ipcheckblock: IPCHECK
+{
+ IPcheck_clear_config();
+}
+'{' ipcheckitems '}' ';';
+
+ipcheckitems: ipcheckitem | ipcheckitems ipcheckitem;
+ipcheckitem: ipcheck_except;
+ipcheck_except: EXCEPT ipcheck_except_ips ';';
+ipcheck_except_ips: ipcheck_except_ip_mask
+ | ipcheck_except_ips ipcheck_except_ip_mask;
+ipcheck_except_ip_mask: QSTRING
+{
+ if (IPcheck_except($1)) {
+ parse_error("IPCheck except: Unable to parse '%s' as an IP mask.",
+ $1);
+ }
+ MyFree($1);
+};
commit 6b6112a74c4b36377f6b5142346ecd2c21021927
Author: Michael Poole <[email protected]>
Date: Sun Sep 12 14:25:03 2021 -0400
Slightly clean up ip_registry_find()
Clarify the documentation comment. Only calculate `bits` one time; it
does not depend on the IP addresses that `canon` is compared against.
diff --git a/ircd/IPcheck.c b/ircd/IPcheck.c
index 1eb74b86..80185ff2 100644
--- a/ircd/IPcheck.c
+++ b/ircd/IPcheck.c
@@ -131,8 +131,10 @@ static unsigned int ip_registry_hash(const struct
irc_in_addr *ip)
}
/** Find an IP registry entry if one exists for the IP address.
- * If \a ip looks like an IPv6 address, only consider the first 64 bits
- * of the address. Otherwise, only consider the final 32 bits.
+ *
+ * If \a ip canonicalizes to a 6to4 mapped IPv6 address, use the first
+ * 48 bits to detect matches. Otherwise use the first 64 bits.
+ *
* @param[in] ip IP address to search for.
* @return Matching registry entry, or NULL if none exists.
*/
@@ -140,10 +142,12 @@ static struct IPRegistryEntry* ip_registry_find(const
struct irc_in_addr *ip)
{
struct irc_in_addr canon;
struct IPRegistryEntry* entry;
+ int bits;
+
ip_registry_canonicalize(&canon, ip);
+ bits = (canon.in6_16[0] == htons(0x2002)) ? 48 : 64;
entry = hashTable[ip_registry_hash(&canon)];
for ( ; entry; entry = entry->next) {
- int bits = (canon.in6_16[0] == htons(0x2002)) ? 48 : 64;
if (ipmask_check(&canon, &entry->addr, bits))
break;
}
-----------------------------------------------------------------------
Summary of changes:
doc/example.conf | 12 ++++++
include/IPcheck.h | 2 +
ircd/IPcheck.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++------
ircd/ircd_lexer.l | 2 +
ircd/ircd_parser.y | 25 +++++++++++-
ircd/s_misc.c | 2 +-
6 files changed, 143 insertions(+), 14 deletions(-)
hooks/post-receive
--
Undernet IRC Server Source Code.
--
You received this message because you are subscribed to the Google Groups
"Undernet Mailing List - [email protected]" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].