/***********************************************************************
X3 ChangeLog
+2006-12-12 Alex Schumann <rubin@afternet.org>
+
+ * configure.in: making google core lib optional
+
+ * configure: regenerated
+
+ * src/proto-p10.c: added support for sending nefarious marks
+
+ * src/proto.h: prototype for irc_mark
+
+ * src/opserv.help: documented new mark support. Also documented the
+ svsjoin and svspart commands as they were missing.
+
+ * src/hash.h: added MARKLEN define
+
+ * src/opserv.c: added mark command as well as mark support in trace
+ and addalert.
+
2006-12-12 Neil Spierling <sirvulcan@gmail.com>
* configure: Regenerated.
#! /bin/sh
-# From configure.in Id: configure.in 1721 2006-08-07 03:05:14Z sirvulcan .
+# From configure.in Id: configure.in 1829 2006-12-12 10:50:48Z sirvulcan .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.60 for X3 1.5.
#
if test $ac_cv_header_google_coredumper_h = yes; then
:
else
- { { echo "$as_me:$LINENO: error: google/coredumper.h, the coredumper headers, were not found. Install coredumper or use --with-coredumper=PATH to tell me how to find it, where PATH/include/google/coredumper.h exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory." >&5
-echo "$as_me: error: google/coredumper.h, the coredumper headers, were not found. Install coredumper or use --with-coredumper=PATH to tell me how to find it, where PATH/include/google/coredumper.h exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory." >&2;}
- { (exit 1); exit 1; }; }
+ { echo "$as_me:$LINENO: result: google/coredumper.h, the coredumper headers, were not found. Install coredumper or use --with-coredumper=PATH to tell me how to find it, where PATH/include/google/coredumper.h exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory." >&5
+echo "${ECHO_T}google/coredumper.h, the coredumper headers, were not found. Install coredumper or use --with-coredumper=PATH to tell me how to find it, where PATH/include/google/coredumper.h exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory." >&6; }
fi
LIBS="-lcoredumper $LIBS"
else
- { { echo "$as_me:$LINENO: error: Coredumper library not found. Install coredumper, or use --with-coredumper=PATH to tell me how to find it, where PATH/lib/libcoredumper.so exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory." >&5
-echo "$as_me: error: Coredumper library not found. Install coredumper, or use --with-coredumper=PATH to tell me how to find it, where PATH/lib/libcoredumper.so exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory." >&2;}
- { (exit 1); exit 1; }; }
+ { echo "$as_me:$LINENO: result: Coredumper library not found. Install coredumper, or use --with-coredumper=PATH to tell me how to find it, where PATH/lib/libcoredumper.so exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory." >&5
+echo "${ECHO_T}Coredumper library not found. Install coredumper, or use --with-coredumper=PATH to tell me how to find it, where PATH/lib/libcoredumper.so exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory." >&6; }
fi
dnl General initialization.
AC_REVISION([$Id$])
-AC_PREREQ(2.59)
+AC_PREREQ(2.60)
AC_INIT([X3],[1.5],[evilnet-devel@lists.sourceforge.net])
CODENAME=X3
AC_CONFIG_HEADERS(src/config.h)
CPPFLAGS="-I${HOME}/include -L${HOME}/lib"
LIBS="$LIBS -L${HOME}/lib"
fi
-AC_CHECK_HEADER(google/coredumper.h, , [AC_MSG_ERROR([google/coredumper.h, the coredumper headers, were not found. Install coredumper or use --with-coredumper=PATH to tell me how to find it, where PATH/include/google/coredumper.h exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory.])],)
-AC_CHECK_LIB(coredumper, WriteCoreDump, , [AC_MSG_ERROR([Coredumper library not found. Install coredumper, or use --with-coredumper=PATH to tell me how to find it, where PATH/lib/libcoredumper.so exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory.])])
+AC_CHECK_HEADER(google/coredumper.h, , [AC_MSG_RESULT([google/coredumper.h, the coredumper headers, were not found. Install coredumper or use --with-coredumper=PATH to tell me how to find it, where PATH/include/google/coredumper.h exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory.])],)
+AC_CHECK_LIB(coredumper, WriteCoreDump, , [AC_MSG_RESULT([Coredumper library not found. Install coredumper, or use --with-coredumper=PATH to tell me how to find it, where PATH/lib/libcoredumper.so exists. For conveniance, just type 'tools/core_install.sh' now, to install coredumper in your home directory.])])
AC_DEFINE_UNQUOTED(CODENAME, "${CODENAME}", [Code name for this release])
AC_SUBST(MODULE_OBJS)
#define REALLEN 50
#define TOPICLEN 250
#define CHANNELLEN 200
+#define MARKLEN 20
#define MAXOPLEVEL 999
#define MAXMODEPARAMS 6
{ "OSMSG_ALREADY_THERE", "You are already in $b%s$b." },
{ "OSMSG_NOT_THERE", "You not in $b%s$b." },
{ "OSMSG_JOIN_DONE", "I have joined $b%s$b." },
+ { "OSMSG_MARK_SET", "Set the MARK." },
{ "OSMSG_SVSJOIN_SENT", "Sent the SVSJOIN." },
{ "OSMSG_SVSPART_SENT", "Sent the SVSPART." },
{ "OSMSG_ALREADY_JOINED", "I am already in $b%s$b." },
{ "OSMSG_NOT_ON_CHANNEL", "$b%s$b does not seem to be on $b%s$b." },
{ "OSMSG_KICKALL_DONE", "I have cleared out %s." },
{ "OSMSG_LEAVING", "Leaving $b%s$b." },
+ { "OSMSG_MARK_INVALID", "Sorry, marks must contain only letters, numbers, and dashes ('-')." },
{ "OSMSG_MODE_SET", "I have set the modes for $b%s$b." },
{ "OSMSG_OP_DONE", "Opped the requested lusers." },
{ "OSMSG_OPALL_DONE", "Opped everyone on $b%s$b." },
{ "OSMSG_USER_SEARCH_BAR", "-------------------------------------------" },
{ "OSMSG_USER_SEARCH_COUNT", "There were %4u matches" },
{ "OSMSG_USER_SEARCH_COUNT_BAR", "------------ Found %4u matches -----------" },
+ { "OSMSG_MARK_NO_MARK", "MARK action requires mark criteria (what do you want to mark them as?)" },
{ "OSMSG_SVSJOIN_NO_TARGET", "SVSJOIN action requires chantarget criteria (where should they join?)" },
{ "OSMSG_SVSPART_NO_TARGET", "SVSPART action requires chantarget criteria (where should they join?)" },
{ "OSMSG_CHANNEL_SEARCH_RESULTS", "The following channels were found:" },
typedef struct opservDiscrim {
struct chanNode *channel;
- char *mask_nick, *mask_ident, *mask_host, *mask_info, *mask_version, *server, *reason, *accountmask, *chantarget;
+ char *mask_nick, *mask_ident, *mask_host, *mask_info, *mask_version, *server, *reason, *accountmask, *chantarget, *mark;
irc_in_addr_t ip_mask;
unsigned long limit;
time_t min_ts, max_ts;
REACT_SHUN,
REACT_SVSJOIN,
REACT_SVSPART,
- REACT_VERSION
+ REACT_VERSION,
+ REACT_MARK
} opserv_alert_reaction;
struct opserv_user_alert {
irc_version_user(opserv, target);
}
+static void
+opserv_mark(struct userNode *target, UNUSED_ARG(char *src_handle), UNUSED_ARG(char *reason), char *mark)
+{
+ if(!mark)
+ return;
+ irc_mark(target, mark);
+}
+
static void
opserv_svsjoin(struct userNode *target, UNUSED_ARG(char *src_handle), UNUSED_ARG(char *reason), char *channame)
{
return 1;
}
+int is_valid_mark(char *mark)
+{
+ char *ptr;
+
+ if(!mark || !*mark)
+ return 0;
+ if(strlen(mark) > MARKLEN)
+ return 0;
+
+ for(ptr = mark; *ptr; ptr++) {
+ if(! (isalnum(*ptr) || *ptr == '-'))
+ return 0;
+ }
+
+ return 1;
+}
+
+static MODCMD_FUNC(cmd_mark)
+{
+ char *mark = argv[2];
+ struct userNode *victim = GetUserH(argv[1]);
+
+ if(!victim)
+ reply("MSG_NICK_UNKNOWN", argv[1]);
+ else if(!is_valid_mark(mark))
+ reply("OSMSG_MARK_INVALID");
+ else {
+ irc_mark(victim, mark);
+ reply("OSMSG_MARK_SET");
+ return 1;
+ }
+ return 0;
+}
+
static MODCMD_FUNC(cmd_op)
{
struct mod_chanmode *change;
case REACT_SVSJOIN: reaction = "svsjoin"; break;
case REACT_SVSPART: reaction = "svspart"; break;
case REACT_VERSION: reaction = "version"; break;
+ case REACT_MARK: reaction = "mark"; break;
default: reaction = "<unknown>"; break;
}
reply("OSMSG_ALERT_IS", iter_key(it), reaction, alert->owner);
discrim_copy = strdup(text_discrim); /* save a copy of the discrim */
wordc = split_line(discrim_copy, false, ArrayLength(wordv), wordv);
alert->discrim = opserv_discrim_create(req, opserv, wordc, wordv, 0);
+ /* Check for missing required criteria or broken records */
if (!alert->discrim || (reaction==REACT_SVSJOIN && !alert->discrim->chantarget) ||
- (reaction==REACT_SVSPART && !alert->discrim->chantarget)) {
+ (reaction==REACT_SVSPART && !alert->discrim->chantarget) ||
+ (reaction==REACT_MARK && !alert->discrim->mark)) {
free(alert->text_discrim);
free(discrim_copy);
free(alert);
reaction = REACT_SVSPART;
else if (!irccasecmp(react, "version"))
reaction = REACT_VERSION;
+ else if (!irccasecmp(react, "mark"))
+ reaction = REACT_MARK;
else {
log_module(OS_LOG, LOG_ERROR, "Invalid reaction %s for alert %s.", react, key);
return 0;
case REACT_SVSJOIN: reaction = "svsjoin"; break;
case REACT_SVSPART: reaction = "svspart"; break;
case REACT_VERSION: reaction = "version"; break;
+ case REACT_MARK: reaction = "mark"; break;
default:
reaction = NULL;
log_module(OS_LOG, LOG_ERROR, "Invalid reaction type %d for alert %s (while writing database).", alert->reaction, iter_key(it));
goto fail;
}
discrim->chantarget = argv[++i];
+ } else if (irccasecmp(argv[i], "mark") == 0) {
+ if(!is_valid_mark(argv[i+1])) {
+ send_message(user, bot, "OSMSG_MARK_INVALID");
+ goto fail;
+ }
+ discrim->mark = argv[++i];
} else if (irccasecmp(argv[i], "authed") == 0) {
i++; /* true_string and false_string are macros! */
if (true_string(argv[i])) {
return 0;
}
+static int
+trace_mark_func(struct userNode *match, void *extra)
+{
+ struct discrim_and_source *das = extra;
+ char *mark = das->discrim->mark;
+
+ if(!mark)
+ return 1;
+ irc_mark(match, mark);
+ return 0;
+}
+
static int
trace_svsjoin_func(struct userNode *match, void *extra)
{
action = trace_svspart_func;
else if (!irccasecmp(argv[1], "version"))
action = trace_version_func;
+ else if (!irccasecmp(argv[1], "mark"))
+ action = trace_mark_func;
else {
reply("OSMSG_BAD_ACTION", argv[1]);
return 0;
reply("OSMSG_SVSPART_NO_TARGET");
ret = 0;
}
+ else if (action == trace_mark_func && !das.discrim->mark) {
+ reply("OSMSG_MARK_NO_MARK");
+ ret = 0;
+ }
else {
matches = opserv_discrim_search(das.discrim, action, &das);
if(!user->version_reply)
opserv_version(user);
break;
+ case REACT_MARK:
+ opserv_mark(user, alert->owner, alert->discrim->reason, alert->discrim->mark);
+ break;
default:
log_module(OS_LOG, LOG_ERROR, "Invalid reaction type %d for alert %s.", alert->reaction, key);
/* fall through to REACT_NOTICE case */
reaction = REACT_SVSPART;
else if(!irccasecmp(argv[2], "version"))
reaction = REACT_VERSION;
+ else if(!irccasecmp(argv[2], "mark"))
+ reaction = REACT_MARK;
else {
reply("OSMSG_UNKNOWN_REACTION", argv[2]);
return 0;
opserv_define_func("ADDALERT SVSJOIN", NULL, 999, 0, 0);
opserv_define_func("ADDALERT SVSPART", NULL, 999, 0, 0);
opserv_define_func("ADDALERT VERSION", NULL, 999, 0, 0);
+ opserv_define_func("ADDALERT MARK", NULL, 999, 0, 0);
opserv_define_func("ADDBAD", cmd_addbad, 800, 0, 2);
opserv_define_func("ADDEXEMPT", cmd_addexempt, 800, 0, 2);
opserv_define_func("ADDTRUST", cmd_addtrust, 800, 0, 5);
opserv_define_func("KICKBANALL", cmd_kickbanall, 450, 2, 0);
opserv_define_func("LOG", cmd_log, 900, 0, 2);
opserv_define_func("MODE", cmd_mode, 100, 2, 2);
+ opserv_define_func("MARK", cmd_mark, 900, 0, 3);
opserv_define_func("OP", cmd_op, 100, 2, 2);
opserv_define_func("OPALL", cmd_opall, 400, 2, 0);
opserv_define_func("HOP", cmd_hop, 100, 2, 2);
opserv_define_func("TRACE VERSION", NULL, 999, 0, 0);
opserv_define_func("TRACE SVSJOIN", NULL, 999, 0, 0);
opserv_define_func("TRACE SVSPART", NULL, 999, 0, 0);
+ opserv_define_func("TRACE MARK", NULL, 999, 0, 0);
opserv_define_func("UNBAN", cmd_unban, 100, 2, 2);
opserv_define_func("UNGAG", cmd_ungag, 600, 0, 2);
opserv_define_func("UNGLINE", cmd_ungline, 600, 0, 2);
"$bSVSJOIN$b: Force users to join channel givin in chantarget criteria.",
"$bSVSPART$b: Force part the matching clients out of the specified target channel.",
"$bVERSION$b: Query for the users CTCP VERSION reply.",
+ "$bMARK$b: Set a nefarius 'mark' named via the mark criteria as if the user were in that dnsbl.",
"Note: By default, IRC operators are not affected by the KILL, GLINE, SHUN or GAG actions. You can override this by specifying the $bABUSE OPERS$b criteria for a trace. Even if you do specify $bABUSE OPERS$b, it will not affect opers at your access level or above.",
"$uSee Also:$u trace criteria, trace"
);
"$bSILENT$b yes/no If yes, AUTO is prepended to the gline message, making the gline silent in nefarious ircd.",
"$bVERSION$b version If they have been queried using the VERSION action and responded, they are matched if the reply they give matches.",
"$CHANTARGET$b #channel For use with SVSJOIN action, this specifies the channel they are svsjoined to.",
+ "$MARK$b mark For use with the MARK action, this is what thety are marked with.",
"Additionally, the $bCHANNEL$b target may be prefixed with @ to select channel operators, + to select voiced users (will not select chanops unless @ is also used), or - to select non-voiced non-chanop users. For example, CHANNEL #foo will select all users in #foo; CHANNEL +#foo will select only users voiced in #foo; CHANNEL @+#foo will select ops and voiced users in #foo; etc.",
"When searching on the criteria of nick, ident, or info, the search string can be another of the three, prefixed with a & character, to indicate that the match should compare each user's individual data. For example, $binfo &nick$b would search for all users whose info matches their nick. To search for that phrase explicitly, prefix the & with a backslash; e.g.: $binfo \&ident$b.",
"$uSee Also:$u trace action, trace"
"$uSee Also:$u ban, kick, kickban"
);
+"MARK" ("/msg $O MARK <mark>",
+ "Sets a nefarious 'mark' on the user as if they are in <mark> dnsbl. ",
+ "(shows in /whois and prefixes their host, for easy banning)",
+ "Mark must be a-z0-9 or dash (-) 20 chars or less.",
+ "$uSee Also:$u trace action"
+ );
+
+"SVSJOIN" ("/msg $O SVSJOIN <nick> <#channel>",
+ "Forces nick to join #channel",
+ "$uSee Also:$u svspart, join, trace action"
+ );
+
+"SVSPART" ("/msg $O SVSPART <nick> <#channel>",
+ "Forces nick to part #channel",
+ "$uSee Also:$u svsjoin, part, trace action"
+ );
+
"MODE" ("/msg $O MODE <#channel> <+/- mode>",
"Sets the specified modes (but cannot include voice, ban or op changes) on a channel.",
"If the channel is omitted, then $bmode$b will be done in the channel where the command was given.",
putsock(":%s %03d %s %s", self->name, num, user->nick, buffer);
}
+void
+irc_mark(struct userNode *user, char *mark)
+{
+ char *host = user->hostname;
+ /* if the mark will put us over the host length, clip some off the left hand side
+ * to make room...
+ */
+ if(strlen(host) + 1 + strlen(mark) > HOSTLEN)
+ host += 1 + ( (strlen(host) + 1 + strlen(mark)) - HOSTLEN );
+ putsock("%s " CMD_MARK " %s DNSBL +m %s.%s", self->numeric, user->nick, mark, host);
+ putsock("%s " CMD_MARK " %s DNSBL_DATA %s", self->numeric, user->nick, mark);
+ /* If they are not otherwise marked, mark their host with fakehost */
+ if(!IsFakeHost(user) && !IsSetHost(user) && !(IsHiddenHost(user) && user->handle_info) )
+ {
+ putsock("%s " CMD_MODE " %s +x", self->numeric, user->nick);
+ putsock("%s " CMD_FAKEHOST " %s %s.%s", self->numeric, user->numeric, mark, host);
+ }
+}
+
static void send_burst(void);
static void
return res;
}
+/* TODO:
+ * This is a stub that doesn't actually do anything. It should be completed
+ * so that bans on *!*@markname.* match users as it does in nefarious
+ */
+static CMD_FUNC(cmd_mark)
+{
+ struct userNode *target;
+ /*
+ * log_module(MAIN_LOG, LOG_ERROR, "DEBUG: mark, user %s, type %s, arg %s", argv[1], argv[2], argv[3]);
+ */
+
+ if(argc < 4)
+ return 0;
+ target = GetUserH(argv[1]);
+ if(!target) {
+ log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose mark is changing.", argv[1]);
+ return 0;
+ }
+ if(!strcasecmp(argv[2], "DNSBL")) {
+ /* DNSBL <modes> */
+ return 1;
+ }
+ else if(!strcasecmp(argv[2], "DNSBL_DATA")) {
+ /* DNSBL_DATA name */
+ return 1;
+
+ }
+ /* unknown type of mark */
+ return 1;
+}
+
static CMD_FUNC(cmd_mode)
{
struct chanNode *cn;
dict_insert(irc_func_dict, TOK_EOB_ACK, cmd_eob_ack);
dict_insert(irc_func_dict, CMD_MODE, cmd_mode);
dict_insert(irc_func_dict, TOK_MODE, cmd_mode);
+ dict_insert(irc_func_dict, CMD_MARK, cmd_mark);
+ dict_insert(irc_func_dict, TOK_MARK, cmd_mark);
dict_insert(irc_func_dict, CMD_NICK, cmd_nick);
dict_insert(irc_func_dict, TOK_NICK, cmd_nick);
dict_insert(irc_func_dict, CMD_ACCOUNT, cmd_account);
dict_insert(irc_func_dict, TOK_WALLUSERS, cmd_dummy);
/* Ignore dnsbl exemptions */
dict_insert(irc_func_dict, TOK_EXEMPT, cmd_dummy);
- dict_insert(irc_func_dict, TOK_MARK, cmd_dummy);
dict_insert(irc_func_dict, CMD_PRIVS, cmd_privs);
dict_insert(irc_func_dict, TOK_PRIVS, cmd_privs);
/* Ignore remote luser */
void irc_account(struct userNode *user, const char *stamp, time_t timestamp);
void irc_regnick(struct userNode *user);
void irc_fakehost(struct userNode *user, const char *host);
+void irc_mark(struct userNode *user, char *mark);
/* numeric messages */
void irc_numeric(struct userNode *user, unsigned int num, const char *format, ...);