unsigned int match_opers : 1, option_log : 1;
unsigned int chan_req_modes : 2, chan_no_modes : 2;
int authed : 2, info_space : 2;
+ unsigned int intra_scmp : 2, intra_dcmp : 2;
time_t min_ts, max_ts;
unsigned int use_regex : 1;
} *discrim_t;
typedef enum {
REACT_NOTICE,
REACT_KILL,
+ REACT_SILENT,
REACT_GLINE,
REACT_SHUN
} opserv_alert_reaction;
}
static struct gline *
-opserv_block(struct userNode *target, char *src_handle, char *reason, unsigned long duration)
+opserv_block(struct userNode *target, char *src_handle, char *reason, unsigned long duration, int silent)
{
char *mask;
mask = alloca(MAXLEN);
snprintf(reason, MAXLEN, "G-line requested by %s.", src_handle);
}
if (!duration) duration = opserv_conf.block_gline_duration;
- return gline_add(src_handle, mask, duration, reason, now, 1);
+ return gline_add(src_handle, mask, duration, reason, now, 1, silent ? 1 : 0);
}
static MODCMD_FUNC(cmd_block)
return 0;
}
reason = (argc > 2) ? unsplit_string(argv+2, argc-2, NULL) : NULL;
- gline = opserv_block(target, user->handle_info->handle, reason, 0);
+ gline = opserv_block(target, user->handle_info->handle, reason, 0, 0);
reply("OSMSG_GLINE_ISSUED", gline->target);
return 1;
}
reply("MSG_INVALID_DURATION", argv[2]);
return 0;
}
- gline = gline_add(user->handle_info->handle, argv[1], duration, reason, now, 1);
+ gline = gline_add(user->handle_info->handle, argv[1], duration, reason, now, 1, 0);
reply("OSMSG_GLINE_ISSUED", gline->target);
return 1;
}
switch (alert->reaction) {
case REACT_NOTICE: reaction = "notice"; break;
case REACT_KILL: reaction = "kill"; break;
+ case REACT_SILENT: reaction = "silent"; break;
case REACT_GLINE: reaction = "gline"; break;
case REACT_SHUN: reaction = "shun"; break;
default: reaction = "<unknown>"; break;
} else if (ohi->clients.used > limit) {
char target[18];
sprintf(target, "*@%s", inet_ntoa(user->ip));
- gline_add(opserv->nick, target, opserv_conf.clone_gline_duration, "AUTO Excessive connections from a single host.", now, 1);
+ gline_add(opserv->nick, target, opserv_conf.clone_gline_duration, "Excessive connections from a single host.", now, 1, 1);
}
}
discrim->max_channels = INT_MAX;
discrim->authed = -1;
discrim->info_space = -1;
+ discrim->intra_scmp = 0;
+ discrim->intra_dcmp = 0;
discrim->use_regex = 0;
dupmask = strdup(hostmask);
if (split_ircmask(dupmask, &discrim->mask_nick, &discrim->mask_ident, &discrim->mask_host)) {
reaction = REACT_NOTICE;
else if (!irccasecmp(react, "kill"))
reaction = REACT_KILL;
+ else if (!irccasecmp(react, "silent"))
+ reaction = REACT_SILENT;
else if (!irccasecmp(react, "gline"))
reaction = REACT_GLINE;
else if (!irccasecmp(react, "shun"))
switch (alert->reaction) {
case REACT_NOTICE: reaction = "notice"; break;
case REACT_KILL: reaction = "kill"; break;
+ case REACT_SILENT: reaction = "silent"; break;
case REACT_GLINE: reaction = "gline"; break;
case REACT_SHUN: reaction = "shun"; break;
default:
discrim->max_channels = INT_MAX;
discrim->authed = -1;
discrim->info_space = -1;
+ discrim->intra_dcmp = 0;
+ discrim->intra_scmp = 0;
for (i=0; i<argc; i++) {
if (irccasecmp(argv[i], "log") == 0) {
send_message(user, bot, "MSG_MISSING_PARAMS", argv[i]);
goto fail;
}
+ if (argv[i+1][0] == '&') {
+ /* Looking for intra-userNode matches */
+ char *tmp = &(argv[i+1][1]);
+ if (strcasecmp(tmp, argv[i]) != 0) { /* Don't allow "nick &nick" etc */
+ if (!strcasecmp(tmp, "nick"))
+ discrim->intra_dcmp = 1;
+ else if (!strcasecmp(tmp, "ident"))
+ discrim->intra_dcmp = 2;
+ else if (!strcasecmp(tmp, "info"))
+ discrim->intra_dcmp = 3;
+ }
+ }
if (irccasecmp(argv[i], "mask") == 0) {
if (!is_ircmask(argv[++i])) {
send_message(user, bot, "OSMSG_INVALID_IRCMASK", argv[i]);
goto fail;
}
} else if (irccasecmp(argv[i], "nick") == 0) {
- discrim->mask_nick = argv[++i];
+ i++;
+ if (discrim->intra_dcmp > 0)
+ discrim->intra_scmp = 1;
+ else
+ discrim->mask_nick = argv[i];
} else if (irccasecmp(argv[i], "ident") == 0) {
- discrim->mask_ident = argv[++i];
+ i++;
+ if (discrim->intra_dcmp > 0)
+ discrim->intra_scmp = 2;
+ else
+ discrim->mask_ident = argv[i];
} else if (irccasecmp(argv[i], "host") == 0) {
discrim->mask_host = argv[++i];
} else if (irccasecmp(argv[i], "info") == 0) {
- discrim->mask_info = argv[++i];
+ i++;
+ if (discrim->intra_dcmp > 0)
+ discrim->intra_scmp = 3;
+ else
+ discrim->mask_info = argv[i];
} else if (irccasecmp(argv[i], "server") == 0) {
discrim->server = argv[++i];
} else if (irccasecmp(argv[i], "ip") == 0) {
discrim_match(discrim_t discrim, struct userNode *user)
{
unsigned int access;
+ char *scmp=NULL, *dcmp=NULL;
if ((user->timestamp < discrim->min_ts)
|| (user->timestamp > discrim->max_ts)
}
}
+ if ((discrim->intra_scmp > 0 && discrim->intra_dcmp > 0)) {
+ switch(discrim->intra_scmp) {
+ case 1: scmp=user->nick; break;
+ case 2: scmp=user->ident; break;
+ case 3:
+ scmp=user->info;
+ if (discrim->info_space == 1) scmp++;
+ break;
+ }
+ switch(discrim->intra_dcmp) {
+ case 1: dcmp=user->nick; break;
+ case 2: dcmp=user->ident; break;
+ case 3: /* When checking INFO, and info_space is enabled
+ * ignore the first character in a search
+ * XXX: Should we ignore ALL leading whitespace?
+ * Also, what about ignoring ~ in ident?
+ */
+ dcmp=user->info;
+ if (discrim->info_space == 1) dcmp++;
+ break;
+ }
+ if (irccasecmp(scmp,dcmp))
+ return 0;
+ }
+
if (discrim->channel && !GetUserMode(discrim->channel, user)) return 0;
access = user->handle_info ? user->handle_info->opserv_level : 0;
if ((access < discrim->min_level)
struct discrim_and_source *das = extra;
if (is_oper_victim(das->source, match, das->discrim->match_opers)) {
- opserv_block(match, das->source->handle_info->handle, das->discrim->reason, das->discrim->duration);
+ opserv_block(match, das->source->handle_info->handle, das->discrim->reason, das->discrim->duration, 0);
}
return 0;
case REACT_KILL:
DelUser(user, opserv, 1, alert->discrim->reason);
return 1;
+ case REACT_SILENT:
+ opserv_block(user, alert->owner, alert->discrim->reason, alert->discrim->duration, 1);
+ return 1;
case REACT_GLINE:
- opserv_block(user, alert->owner, alert->discrim->reason, alert->discrim->duration);
+ opserv_block(user, alert->owner, alert->discrim->reason, alert->discrim->duration, 0);
return 1;
case REACT_SHUN:
opserv_shun(user, alert->owner, alert->discrim->reason, alert->discrim->duration);
reaction = REACT_NOTICE;
else if (!irccasecmp(argv[2], "kill"))
reaction = REACT_KILL;
+ else if (!irccasecmp(argv[2], "silent"))
+ reaction = REACT_SILENT;
else if (!irccasecmp(argv[2], "gline"))
reaction = REACT_GLINE;
else if (!irccasecmp(argv[2], "shun"))
opserv_define_func("ACCESS", cmd_access, 0, 0, 0);
opserv_define_func("ADDALERT", cmd_addalert, 800, 0, 4);
opserv_define_func("ADDALERT NOTICE", NULL, 0, 0, 0);
+ opserv_define_func("ADDALERT SILENT", NULL, 900, 0, 0);
opserv_define_func("ADDALERT GLINE", NULL, 900, 0, 0);
opserv_define_func("ADDALERT SHUN", NULL, 900, 0, 0);
opserv_define_func("ADDALERT KILL", NULL, 900, 0, 0);