aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common.c1
-rw-r--r--src/kike.c78
2 files changed, 73 insertions, 6 deletions
diff --git a/src/common.c b/src/common.c
index 73f8e5c..4b72e39 100644
--- a/src/common.c
+++ b/src/common.c
@@ -43,6 +43,7 @@
#include <regex.h>
#include <libgen.h>
#include <syslog.h>
+#include <fnmatch.h>
#include <sys/socket.h>
#include <sys/types.h>
diff --git a/src/kike.c b/src/kike.c
index 0082179..7632a35 100644
--- a/src/kike.c
+++ b/src/kike.c
@@ -514,10 +514,13 @@ enum
IRC_RPL_LUSERCHANNELS = 254,
IRC_RPL_LUSERME = 255,
+ IRC_RPL_VERSION = 351,
IRC_RPL_MOTD = 372,
IRC_RPL_MOTDSTART = 375,
IRC_RPL_ENDOFMOTD = 376,
+ IRC_RPL_TIME = 391,
+ IRC_ERR_NOSUCHSERVER = 402,
IRC_ERR_NOORIGIN = 409,
IRC_ERR_UNKNOWNCOMMAND = 421,
IRC_ERR_NOMOTD = 422,
@@ -542,10 +545,13 @@ static const char *g_default_replies[] =
[IRC_RPL_LUSERCHANNELS] = "%d :channels formed",
[IRC_RPL_LUSERME] = ":I have %d clients and %d servers",
+ [IRC_RPL_VERSION] = "%s.%d %s :%s",
[IRC_RPL_MOTD] = ":- %s",
[IRC_RPL_MOTDSTART] = ":- %s Message of the day - ",
[IRC_RPL_ENDOFMOTD] = ":End of MOTD command",
+ [IRC_RPL_TIME] = "%s :%s",
+ [IRC_ERR_NOSUCHSERVER] = "%s :No such server",
[IRC_ERR_NOORIGIN] = ":No origin specified",
[IRC_ERR_UNKNOWNCOMMAND] = "%s: Unknown command",
[IRC_ERR_NOMOTD] = ":MOTD File is missing",
@@ -625,6 +631,12 @@ irc_send_lusers (struct client *c)
}
static bool
+irc_is_this_me (struct server_context *ctx, const char *target)
+{
+ return !fnmatch (target, ctx->server_name, 0);
+}
+
+static void
irc_try_finish_registration (struct client *c)
{
struct server_context *ctx = c->ctx;
@@ -738,16 +750,65 @@ irc_handle_user (const struct irc_message *msg, struct client *c)
}
static void
+irc_handle_lusers (const struct irc_message *msg, struct client *c)
+{
+ if (msg->params.len > 1 && !irc_is_this_me (c->ctx, msg->params.vector[1]))
+ {
+ irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[1]);
+ return;
+ }
+ else
+ irc_send_lusers (c);
+
+}
+
+static void
+irc_handle_motd (const struct irc_message *msg, struct client *c)
+{
+ if (msg->params.len > 0 && !irc_is_this_me (c->ctx, msg->params.vector[0]))
+ irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[0]);
+ else
+ irc_send_motd (c);
+}
+
+static void
irc_handle_ping (const struct irc_message *msg, struct client *c)
{
// XXX: the RFC is pretty incomprehensible about the exact usage
- if (msg->params.len < 1)
+ if (msg->params.len > 1 && !irc_is_this_me (c->ctx, msg->params.vector[1]))
+ irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[1]);
+ else if (msg->params.len < 1)
irc_send_reply (c, IRC_ERR_NOORIGIN);
else
irc_send (c, ":%s PONG :%s",
c->ctx->server_name, msg->params.vector[0]);
}
+static void
+irc_handle_time (const struct irc_message *msg, struct client *c)
+{
+ if (msg->params.len > 0 && !irc_is_this_me (c->ctx, msg->params.vector[0]))
+ irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[0]);
+ else
+ {
+ char buf[32];
+ time_t now = time (NULL);
+ struct tm tm;
+ strftime (buf, sizeof buf, "%a %b %d %Y %T", localtime_r (&now, &tm));
+ irc_send_reply (c, IRC_RPL_TIME, c->ctx->server_name, buf);
+ }
+}
+
+static void
+irc_handle_version (const struct irc_message *msg, struct client *c)
+{
+ if (msg->params.len > 0 && !irc_is_this_me (c->ctx, msg->params.vector[0]))
+ irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[0]);
+ else
+ irc_send_reply (c, IRC_RPL_VERSION, PROGRAM_VERSION, g_debug_mode,
+ c->ctx->server_name, PROGRAM_NAME " " PROGRAM_VERSION);
+}
+
// -----------------------------------------------------------------------------
struct irc_command
@@ -760,13 +821,18 @@ struct irc_command
static void
irc_register_handlers (struct server_context *ctx)
{
+ // TODO: add an index for IRC_ERR_NOSUCHSERVER validation?
static const struct irc_command message_handlers[] =
{
- { "PASS", false, irc_handle_pass },
- { "NICK", false, irc_handle_nick },
- { "USER", false, irc_handle_user },
-
- { "PING", true, irc_handle_ping }
+ { "PASS", false, irc_handle_pass },
+ { "NICK", false, irc_handle_nick },
+ { "USER", false, irc_handle_user },
+
+ { "LUSERS", true, irc_handle_lusers },
+ { "MOTD", true, irc_handle_motd },
+ { "PING", true, irc_handle_ping },
+ { "TIME", true, irc_handle_time },
+ { "VERSION", true, irc_handle_version },
};
for (size_t i = 0; i < N_ELEMENTS (message_handlers); i++)