Add 250 as valid response to LUSERS command (#138).
[jelmer/ctrlproxy.git] / src / redirect.c
index 4dab70f31d4e88ac935458257d0812727fc2cd7e..1ec1cd5d963e2750248213b2169969562d6609fb 100644 (file)
@@ -47,8 +47,10 @@ struct query {
        int (*handle) (const struct line *, const struct network *n, struct client *c, struct query *);
 };
 
-static int handle_default(const struct line *, const struct network *n, struct client *c, struct query *);
-static int handle_topic(const struct line *, const struct network *n, struct client *c, struct query *);
+static int handle_default(const struct line *, const struct network *n, 
+                                                 struct client *c, struct query *);
+static int handle_topic(const struct line *, const struct network *n, 
+                                               struct client *c, struct query *);
 
 static struct query queries[] = {
 /* Commands that get a one-client reply: 
@@ -57,7 +59,7 @@ static struct query queries[] = {
                { RPL_WHOISUSER, RPL_WHOISCHANNELS, RPL_AWAY,
                  RPL_WHOISIDLE, RPL_WHOISCHANNELS, RPL_WHOISIP,
                  RPL_WHOISSERVER, RPL_WHOISOPERATOR, RPL_WHOISACTUALLY,
-                 RPL_WHOISIDENTIFIED, 0 }, 
+                 RPL_WHOISACCOUNT, RPL_WHOISIDENTIFIED, 0 }, 
                { RPL_ENDOFWHOIS, 0 }, 
                { ERR_NOSUCHSERVER, ERR_NONICKNAMEGIVEN, ERR_NOSUCHNICK, 0 },
                handle_default
@@ -65,7 +67,7 @@ static struct query queries[] = {
 
        /* WHO [<name> [<o>]] */
        {"WHO", 
-           { RPL_WHOREPLY, 0 }, 
+           { RPL_WHOREPLY, RPL_WHOSPCRPL, 0 }, 
                { RPL_ENDOFWHO, 0 },
                { ERR_NOSUCHSERVER, 0 },
                handle_default 
@@ -98,7 +100,7 @@ static struct query queries[] = {
        
  /* WHOWAS <nickname> [<count> [<server>]]*/
        {"WHOWAS", 
-               { RPL_WHOWASUSER, RPL_WHOISSERVER, RPL_WHOWAS_TIME,  0 },
+               { RPL_WHOWASUSER, RPL_WHOISSERVER, RPL_WHOWAS_TIME, 0 },
                { RPL_ENDOFWHOWAS, 0 },
                { ERR_NONICKNAMEGIVEN, ERR_WASNOSUCHNICK, 0 },
                handle_default
@@ -109,8 +111,9 @@ static struct query queries[] = {
                { RPL_STATSCLINE, RPL_STATSILINE, RPL_STATSQLINE, 
                  RPL_STATSLINKINFO, RPL_STATSCOMMANDS, RPL_STATSHLINE, RPL_STATSNLINE,
                  RPL_STATSKLINE, RPL_STATSLLINE, RPL_STATSUPTIME, RPL_STATSOLINE, 
+                 RPL_STATSTLINE,
                  0 },
-               { RPL_ENDOFSTATS, 0 },
+               { RPL_TRYAGAIN, RPL_ENDOFSTATS, 0 },
                { ERR_NOSUCHSERVER, 0 },
                handle_default
        }, 
@@ -184,12 +187,13 @@ static struct query queries[] = {
 
 /* JOIN <channel>{,<channel>} [<key>{,<key>}] */
        {"JOIN",
-               { RPL_TOPIC, RPL_TOPICWHOTIME, RPL_CREATIONTIME, 0 },
+               { 0 },
                { 0 },
                { ERR_NEEDMOREPARAMS, ERR_BANNEDFROMCHAN,
                  ERR_INVITEONLYCHAN, ERR_BADCHANNELKEY,
                  ERR_CHANNELISFULL, ERR_BADCHANMASK,
-                 ERR_NOSUCHCHANNEL, ERR_TOOMANYCHANNELS, 0 },
+                 ERR_FORWARDING, ERR_NOSUCHCHANNEL, 
+                 ERR_TOOMANYCHANNELS, 0 },
                handle_default
        },
 
@@ -258,7 +262,7 @@ static struct query queries[] = {
                        
                        /* Replies to channel mode queries */
                        ERR_USERNOTINCHANNEL, ERR_KEYSET, ERR_CHANOPPRIVSNEEDED,
-                       ERR_UNKNOWNMODE, ERR_NOCHANMODES, 
+                       ERR_UNKNOWNMODE, ERR_NOCHANMODES, ERR_NOSUCHCHANNEL,
                        
                        0 },
                handle_default
@@ -319,7 +323,7 @@ static struct query queries[] = {
  /* LUSERS [ <mask> [ <target> ] ] */
        { "LUSERS",
                { RPL_LUSERCLIENT, RPL_LUSEROP, RPL_LUSERUNKNOWN, RPL_LUSERCHANNELS, 
-                       RPL_LUSERME, 0 },
+                       RPL_LUSERME, RPL_STATSTLINE, 0 },
                { 0 },
                { ERR_NOSUCHSERVER, 0 },
                handle_default
@@ -493,12 +497,15 @@ static gboolean handle_464(struct network *n, struct line *l)
 }
 
 /* List of responses that should be sent to all clients */
-static int response_all[] = { RPL_NOWAWAY, RPL_UNAWAY, RPL_NAMREPLY, 
+static int response_all[] = { RPL_NOWAWAY, RPL_UNAWAY, 
        ERR_NO_OP_SPLIT, RPL_HIDINGHOST,
-       RPL_ENDOFNAMES, ERR_NEEDREGGEDNICK, RPL_UMODEIS, 
+       ERR_NEEDREGGEDNICK, RPL_UMODEIS, 
        RPL_LUSERCLIENT, RPL_LUSEROP, RPL_LUSERUNKNOWN, RPL_LUSERCHANNELS,
-       RPL_LUSERME, ERR_NO_OP_SPLIT, RPL_LOCALUSERS, RPL_GLOBALUSERS, 0 };
-static int response_none[] = { ERR_NOMOTD, RPL_ENDOFMOTD, 0 };
+       RPL_LUSERME, ERR_NO_OP_SPLIT, RPL_LOCALUSERS, RPL_GLOBALUSERS, 
+       RPL_NAMREPLY, RPL_ENDOFNAMES, RPL_TOPIC, RPL_TOPICWHOTIME, 
+               RPL_CREATIONTIME, 0 };
+static int response_none[] = { ERR_NOMOTD, RPL_MOTDSTART, RPL_MOTD, 
+       RPL_ENDOFMOTD, 0 };
 static struct {
        int response;
        gboolean (*handler) (struct network *n, struct line *);
@@ -511,10 +518,13 @@ static struct {
        { 0, NULL }
 };
 
+/**
+ * Check whether reply r is part of a specified list
+ */
 static int is_reply(const int *replies, int r)
 {
        int i;
-       g_assert(replies);
+       g_assert(replies != NULL);
 
        for(i = 0; i < 20 && replies[i]; i++) {
                if(replies[i] == r) return 1;
@@ -558,14 +568,14 @@ gboolean redirect_response(struct network *network, struct line *l)
                        is_reply(s->query->end_replies, n))) {
                        
                        /* Send to client that queried, if that client still exists */
-                       if (s->client && verify_client(s->network, s->client)) {
+                       if (s->client != NULL && verify_client(s->network, s->client)) {
                                c = s->client;
                                client_send_line(s->client, l);
                        }
 
-                       if(!is_reply(s->query->replies, n)) {
+                       if (!is_reply(s->query->replies, n)) {
                                /* Remove from stack */
-                               if(!p)stack = s->next;  
+                               if (p == NULL)stack = s->next;  
                                else p->next = s->next;
                                g_free(s);
                        }
@@ -612,7 +622,7 @@ void redirect_clear(const struct network *net)
        g_assert(net);
 
        q = stack;
-       while (q) {
+       while (q != NULL) {
                if (q->network != net) {
                        p = q;
                        q = q->next;
@@ -620,7 +630,7 @@ void redirect_clear(const struct network *net)
                }
 
                /* Remove from stack */
-               if(!p)stack = q->next;  
+               if (p == NULL)stack = q->next;  
                else p->next = q->next;
                n = q->next;
                g_free(q);
@@ -628,7 +638,8 @@ void redirect_clear(const struct network *net)
        }
 }
 
-void redirect_record(const struct network *n, struct client *c, const struct line *l)
+void redirect_record(const struct network *n, struct client *c, 
+                                        const struct line *l)
 {
        struct query *q;
 
@@ -637,11 +648,13 @@ void redirect_record(const struct network *n, struct client *c, const struct lin
        g_assert(l->args[0]);
 
        q = find_query(l->args[0]);
-       if(!q) {
-               if (c) {
-                       log_client(LOG_WARNING, c, "Unknown command from client: %s", l->args[0]);
+       if (q == NULL) {
+               if (c != NULL) {
+                       log_client(LOG_WARNING, c, "Unknown command from client: %s", 
+                                          l->args[0]);
                } else {
-                       log_network(LOG_WARNING, n, "Sending unknown command '%s'", l->args[0]);
+                       log_network(LOG_WARNING, n, "Sending unknown command '%s'", 
+                                               l->args[0]);
                }
 
                q = &unknown_query;
@@ -651,12 +664,13 @@ void redirect_record(const struct network *n, struct client *c, const struct lin
        q->handle(l, n, c, q);
 }
 
-static int handle_default(const struct line *l, const struct network *n, struct client *c, struct query *q)
+static int handle_default(const struct line *l, const struct network *n, 
+                                                 struct client *c, struct query *q)
 {
-       struct query_stack *s = g_new(struct query_stack,1);
-       g_assert(l);
-       g_assert(n);
-       g_assert(q);
+       struct query_stack *s = g_new(struct query_stack, 1);
+       g_assert(l != NULL);
+       g_assert(n != NULL);
+       g_assert(q != NULL);
        s->network = n;
        s->client = c;
        s->time = time(NULL);