const char *reason;
unsigned int duration;
unsigned int mask;
+ unsigned int debug : 1;
char zone[1];
};
static dict_t blacklist_reasons; /* maps strings to themselves (poor man's data sharing) */
static struct {
+ struct userNode *debug_bot;
+ struct chanNode *debug_channel;
unsigned long gline_duration;
} conf;
+#if defined(GCC_VARMACROS)
+# define blacklist_debug(ARGS...) do { if (conf.debug_bot && conf.debug_channel) send_channel_message(conf.debug_channel, conf.debug_bot, ARGS); } while (0)
+#elif defined(C99_VARMACROS)
+# define blacklist_debug(...) do { if (conf.debug_bot && conf.debug_channel) send_channel_message(conf.debug_channel, conf.debug_bot, __VA_ARGS__); } while (0)
+#endif
+
static void
do_expandos(char *output, unsigned int out_len, const char *input, ...)
{
message = "client is blacklisted";
}
- /* Expand elements of the message as necessary. */
- do_expandos(reason, sizeof(reason), message, "%txt%", (txt ? txt : "(no-txt)"), "%ip%", data->client_ip, NULL);
+ /* Prepend "AUTO " prefix so the g-lined are put in a different snomask */
+ strcpy(reason, "AUTO ");
- /* Now generate the G-line. */
- target[0] = '*';
- target[1] = '@';
- strcpy(target + 2, data->client_ip);
- gline_add(self->name, target, zone->duration, reason, now, now, 1);
+ /* Expand elements of the message as necessary. */
+ do_expandos(reason + 5, sizeof(reason) - 5, message, "%txt%", (txt ? txt : "(no-txt)"), "%ip%", data->client_ip, NULL);
+
+ if (zone->debug) {
+ blacklist_debug("DNSBL match: [%s] %s (%s)", zone->zone, data->client_ip, reason);
+ } else {
+ /* Now generate the G-line. */
+ target[0] = '*';
+ target[1] = '@';
+ strcpy(target + 2, data->client_ip);
+ gline_add(self->name, target, zone->duration, reason, now, now, 0, 1);
+ }
}
free(txt);
}
-static int
+static void
blacklist_check_user(struct userNode *user)
{
static const char *hexdigits = "0123456789abcdef";
char ip[IRC_NTOP_MAX_SIZE];
char dnsbl_target[128];
+ /* Users added during burst should not be checked. */
+ if (user->uplink->burst)
+ return;
+
/* Users with bogus IPs are probably service bots. */
if (!irc_in_addr_is_valid(user->ip))
- return 0;
+ return;
/* Check local file-based blacklist. */
irc_ntop(ip, sizeof(ip), &user->ip);
target[0] = '*';
target[1] = '@';
strcpy(target + 2, host);
- gline_add(self->name, target, conf.gline_duration, reason, now, now, 1);
+ /* We do not prepend AUTO here so it can be done in the blacklist file. */
+ gline_add(self->name, target, conf.gline_duration, reason, now, now, 0, 1);
}
/* Figure out the base part of a DNS blacklist hostname. */
}
dnsbl_len = 48;
} else {
- return 0;
+ return;
}
/* Start a lookup for the appropriate hostname in each DNSBL. */
if (req) {
data = (struct dnsbl_data*)(req + 1);
strcpy(data->client_ip, ip);
- strcpy(data->zone_name, zone);
+ strcpy(data->zone_name, zone);
}
}
- return 0;
}
static void
if (node == NULL)
return;
+ str1 = database_get_data(node, "debug_bot", RECDB_QSTRING);
+ if (str1)
+ conf.debug_bot = GetUserH(str1);
+
+ str1 = database_get_data(node, "debug_channel", RECDB_QSTRING);
+ if (conf.debug_bot && str1) {
+ str2 = database_get_data(node, "debug_channel_modes", RECDB_QSTRING);
+ if (!str2)
+ str2 = "+tinms";
+ conf.debug_channel = AddChannel(str1, now, str2, NULL);
+ AddChannelUser(conf.debug_bot, conf.debug_channel)->modes |= MODE_CHANOP;
+ } else {
+ conf.debug_channel = NULL;
+ }
+
str1 = database_get_data(node, "file", RECDB_QSTRING);
str2 = database_get_data(node, "file_reason", RECDB_QSTRING);
blacklist_load_file(str1, str2);
zone->duration = str1 ? ParseInterval(str1) : 3600;
str1 = database_get_data(dnsbl, "mask", RECDB_QSTRING);
zone->mask = str1 ? strtoul(str1, NULL, 0) : ~0u;
+ str1 = database_get_data(dnsbl, "debug", RECDB_QSTRING);
+ zone->debug = str1 ? enabled_string(str1) : 0;
zone->reasons.used = 0;
zone->reasons.size = 0;
zone->reasons.list = NULL;