]> jfr.im git - solanum.git/blobdiff - ircd/client.c
strcpy: mass-migrate to strlcpy where appropriate
[solanum.git] / ircd / client.c
index 39d4ea4d839e7d29d5b0568a6f0e3ea6143d5e3d..9ec5c6cc759414fa464462a10985daefab82e1a7 100644 (file)
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
  *  USA
- *
- *  $Id: client.c 3514 2007-06-06 16:25:21Z nenolod $
  */
 #include "stdinc.h"
-#include "config.h"
+#include "defaults.h"
 
 #include "client.h"
 #include "class.h"
-#include "common.h"
 #include "hash.h"
 #include "match.h"
 #include "ircd.h"
 #include "numeric.h"
 #include "packet.h"
-#include "s_auth.h"
+#include "authproc.h"
 #include "s_conf.h"
 #include "s_newconf.h"
 #include "logger.h"
 #include "hook.h"
 #include "msg.h"
 #include "monitor.h"
-#include "blacklist.h"
 #include "reject.h"
 #include "scache.h"
-#include "irc_dictionary.h"
+#include "rb_dictionary.h"
 #include "sslproc.h"
+#include "wsproc.h"
 #include "s_assert.h"
 
 #define DEBUG_EXITED_CLIENTS
@@ -79,9 +76,9 @@ static rb_bh *pclient_heap = NULL;
 static rb_bh *user_heap = NULL;
 static rb_bh *away_heap = NULL;
 static char current_uid[IDLEN];
-static int32_t current_connid = 0;
+static uint32_t current_connid = 0;
 
-struct Dictionary *nd_dict = NULL;
+rb_dictionary *nd_dict = NULL;
 
 enum
 {
@@ -129,9 +126,83 @@ init_client(void)
        rb_event_addish("exit_aborted_clients", exit_aborted_clients, NULL, 1);
        rb_event_add("flood_recalc", flood_recalc, NULL, 1);
 
-       nd_dict = irc_dictionary_create(irccmp);
+       nd_dict = rb_dictionary_create("nickdelay", irccmp);
+}
+
+/*
+ * connid_get - allocate a connid
+ *
+ * inputs       - none
+ * outputs      - a connid token which is used to represent a logical circuit
+ * side effects - current_connid is incremented, possibly multiple times.
+ *                the association of the connid to it's client is committed.
+ */
+uint32_t
+connid_get(struct Client *client_p)
+{
+       s_assert(MyConnect(client_p));
+       if (!MyConnect(client_p))
+               return 0;
+
+       /* find a connid that is available */
+       while (find_cli_connid_hash(++current_connid) != NULL)
+       {
+               /* handle wraparound, current_connid must NEVER be 0 */
+               if (current_connid == 0)
+                       ++current_connid;
+       }
+
+       add_to_cli_connid_hash(client_p, current_connid);
+       rb_dlinkAddAlloc(RB_UINT_TO_POINTER(current_connid), &client_p->localClient->connids);
+
+       return current_connid;
+}
+
+/*
+ * connid_put - free a connid
+ *
+ * inputs       - connid to free
+ * outputs      - nothing
+ * side effects - connid bookkeeping structures are freed
+ */
+void
+connid_put(uint32_t id)
+{
+       struct Client *client_p;
+
+       s_assert(id != 0);
+       if (id == 0)
+               return;
+
+       client_p = find_cli_connid_hash(id);
+       if (client_p == NULL)
+               return;
+
+       del_from_cli_connid_hash(id);
+       rb_dlinkFindDestroy(RB_UINT_TO_POINTER(id), &client_p->localClient->connids);
 }
 
+/*
+ * client_release_connids - release any connids still attached to a client
+ *
+ * inputs       - client to garbage collect
+ * outputs      - none
+ * side effects - client's connids are garbage collected
+ */
+void
+client_release_connids(struct Client *client_p)
+{
+       rb_dlink_node *ptr, *ptr2;
+
+       if (client_p->localClient->connids.head)
+               s_assert(MyConnect(client_p));
+
+       if (!MyConnect(client_p))
+               return;
+
+       RB_DLINK_FOREACH_SAFE(ptr, ptr2, client_p->localClient->connids.head)
+               connid_put(RB_POINTER_TO_UINT(ptr->data));
+}
 
 /*
  * make_client - create a new Client struct and set it to initial state.
@@ -163,17 +234,6 @@ make_client(struct Client *from)
 
                client_p->localClient->F = NULL;
 
-               if(current_connid+1 == 0)
-                       current_connid++;
-
-               client_p->localClient->connid = ++current_connid;
-
-               if(current_connid+1 == 0)
-                       current_connid++;
-
-               client_p->localClient->zconnid = ++current_connid;
-               add_to_cli_connid_hash(client_p);
-
                client_p->preClient = rb_bh_alloc(pclient_heap);
 
                /* as good a place as any... */
@@ -187,7 +247,7 @@ make_client(struct Client *from)
        }
 
        SetUnknown(client_p);
-       strcpy(client_p->username, "unknown");
+       rb_strlcpy(client_p->username, "unknown", sizeof(client_p->username));
 
        return client_p;
 }
@@ -195,17 +255,15 @@ make_client(struct Client *from)
 void
 free_pre_client(struct Client *client_p)
 {
-       struct Blacklist *blptr;
-
        s_assert(NULL != client_p);
 
        if(client_p->preClient == NULL)
                return;
 
-       blptr = client_p->preClient->dnsbl_listed;
-       if (blptr != NULL)
-               unref_blacklist(blptr);
-       s_assert(rb_dlink_list_length(&client_p->preClient->dnsbl_queries) == 0);
+       s_assert(client_p->preClient->auth.cid == 0);
+
+       rb_free(client_p->preClient->auth.data);
+       rb_free(client_p->preClient->auth.reason);
 
        rb_bh_free(pclient_heap, client_p->preClient);
        client_p->preClient = NULL;
@@ -232,7 +290,7 @@ free_local_client(struct Client *client_p)
                client_p->localClient->listener = 0;
        }
 
-       del_from_cli_connid_hash(client_p);
+       client_release_connids(client_p);
        if(client_p->localClient->F != NULL)
        {
                rb_close(client_p->localClient->F);
@@ -253,11 +311,14 @@ free_local_client(struct Client *client_p)
        if (client_p->localClient->privset)
                privilegeset_unref(client_p->localClient->privset);
 
-       if(IsSSL(client_p))
-           ssld_decrement_clicount(client_p->localClient->ssl_ctl);
+       if (IsSSL(client_p))
+               ssld_decrement_clicount(client_p->localClient->ssl_ctl);
 
-       if(IsCapable(client_p, CAP_ZIP))
-           ssld_decrement_clicount(client_p->localClient->z_ctl);
+       if (IsCapable(client_p, CAP_ZIP))
+               ssld_decrement_clicount(client_p->localClient->z_ctl);
+
+       if (client_p->localClient->ws_ctl != NULL)
+               wsockd_decrement_clicount(client_p->localClient->ws_ctl);
 
        rb_bh_free(lclient_heap, client_p->localClient);
        client_p->localClient = NULL;
@@ -350,7 +411,7 @@ check_pings_list(rb_dlink_list * list)
                                             "No response from %s, closing link",
                                             log_client_name(client_p, HIDE_IP));
                                }
-                               (void) rb_snprintf(scratch, sizeof(scratch),
+                               (void) snprintf(scratch, sizeof(scratch),
                                                  "Ping timeout: %d seconds",
                                                  (int) (rb_current_time() - client_p->localClient->lasttime));
 
@@ -396,9 +457,8 @@ check_unknowns_list(rb_dlink_list * list)
                if(IsDead(client_p) || IsClosing(client_p))
                        continue;
 
-               /* still has DNSbls to validate against */
-               if(client_p->preClient != NULL &&
-                               rb_dlink_list_length(&client_p->preClient->dnsbl_queries) > 0)
+               /* Still querying with authd */
+               if(client_p->preClient != NULL && client_p->preClient->auth.cid != 0)
                        continue;
 
                /*
@@ -477,7 +537,7 @@ check_banned_lines(void)
 void
 check_klines_event(void *unused)
 {
-       kline_queued = 0;
+       kline_queued = false;
        check_klines();
 }
 
@@ -544,7 +604,7 @@ check_dlines(void)
                if(IsMe(client_p))
                        continue;
 
-               if((aconf = find_dline((struct sockaddr *)&client_p->localClient->ip,client_p->localClient->ip.ss_family)) != NULL)
+               if((aconf = find_dline((struct sockaddr *)&client_p->localClient->ip, GET_SS_FAMILY(&client_p->localClient->ip))) != NULL)
                {
                        if(aconf->status & CONF_EXEMPTDLINE)
                                continue;
@@ -563,7 +623,7 @@ check_dlines(void)
        {
                client_p = ptr->data;
 
-               if((aconf = find_dline((struct sockaddr *)&client_p->localClient->ip,client_p->localClient->ip.ss_family)) != NULL)
+               if((aconf = find_dline((struct sockaddr *)&client_p->localClient->ip, GET_SS_FAMILY(&client_p->localClient->ip))) != NULL)
                {
                        if(aconf->status & CONF_EXEMPTDLINE)
                                continue;
@@ -672,7 +732,7 @@ resv_nick_fnc(const char *mask, const char *reason, int temp_time)
 
                        /* Do all of the nick-changing gymnastics. */
                        client_p->tsinfo = rb_current_time();
-                       add_history(client_p, 1);
+                       whowas_add_history(client_p, 1);
 
                        monitor_signoff(client_p);
 
@@ -696,7 +756,7 @@ resv_nick_fnc(const char *mask, const char *reason, int temp_time)
                                rb_dlinkDestroy(ptr, &client_p->on_allow_list);
                        }
 
-                       rb_snprintf(note, sizeof(note), "Nick: %s", nick);
+                       snprintf(note, sizeof(note), "Nick: %s", nick);
                        rb_note(client_p->localClient->F, note);
                }
        }
@@ -872,7 +932,7 @@ find_chasing(struct Client *source_p, const char *user, int *chasing)
        if(who || IsDigit(*user))
                return who;
 
-       if(!(who = get_history(user, (long) KILLCHASETIMELIMIT)))
+       if(!(who = whowas_get_history(user, (long) KILLCHASETIMELIMIT)))
        {
                sendto_one_numeric(source_p, ERR_NOSUCHNICK,
                                   form_str(ERR_NOSUCHNICK), user);
@@ -926,16 +986,16 @@ get_client_name(struct Client *client, int showip)
                switch (showip)
                {
                case SHOW_IP:
-                       rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
+                       snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
                                   client->name, client->username,
                                   client->sockhost);
                        break;
                case MASK_IP:
-                       rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@255.255.255.255]",
+                       snprintf(nbuf, sizeof(nbuf), "%s[%s@255.255.255.255]",
                                   client->name, client->username);
                        break;
                default:
-                       rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
+                       snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
                                   client->name, client->username, client->host);
                }
                return nbuf;
@@ -968,12 +1028,12 @@ log_client_name(struct Client *target_p, int showip)
                switch (showip)
                {
                case SHOW_IP:
-                       rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]", target_p->name,
+                       snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]", target_p->name,
                                   target_p->username, target_p->sockhost);
                        break;
 
                default:
-                       rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]", target_p->name,
+                       snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]", target_p->name,
                                   target_p->username, target_p->host);
                }
 
@@ -1019,9 +1079,9 @@ free_exited_clients(void *unused)
                                {
                                        s_assert(0);
                                        sendto_realops_snomask(SNO_GENERAL, L_ALL,
-                                               "On abort_list: %s stat: %u flags: %u/%u handler: %c",
+                                               "On abort_list: %s stat: %u flags: %llu handler: %c",
                                                target_p->name, (unsigned int) target_p->status,
-                                               target_p->flags, target_p->flags2, target_p->handler);
+                                               (unsigned long long)target_p->flags,  target_p->handler);
                                        sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                                "Please report this to the charybdis developers!");
                                        found++;
@@ -1073,7 +1133,7 @@ free_exited_clients(void *unused)
 ** already been sent.  we make sure to exit a server's dependent clients
 ** and servers before the server itself; exit_one_client takes care of
 ** actually removing things off llists.   tweaked from +CSr31  -orabidoo
-*/
+ */
 /*
  * added sanity test code.... source_p->serv might be NULL...
  */
@@ -1126,7 +1186,7 @@ recurse_remove_clients(struct Client *source_p, const char *comment)
 ** Remove *everything* that depends on source_p, from all lists, and sending
 ** all necessary SQUITs.  source_p itself is still on the lists,
 ** and its SQUITs have been sent except for the upstream one  -orabidoo
-*/
+ */
 static void
 remove_dependents(struct Client *client_p,
                  struct Client *source_p,
@@ -1163,9 +1223,9 @@ exit_aborted_clients(void *unused)
                        {
                                s_assert(0);
                                sendto_realops_snomask(SNO_GENERAL, L_ALL,
-                                       "On dead_list: %s stat: %u flags: %u/%u handler: %c",
+                                       "On dead_list: %s stat: %u flags: %llu handler: %c",
                                        abt->client->name, (unsigned int) abt->client->status,
-                                       abt->client->flags, abt->client->flags2, abt->client->handler);
+                                       (unsigned long long)abt->client->flags, abt->client->handler);
                                sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                        "Please report this to the charybdis developers!");
                                continue;
@@ -1193,7 +1253,6 @@ exit_aborted_clients(void *unused)
 
 /*
  * dead_link - Adds client to a list of clients that need an exit_client()
- *
  */
 void
 dead_link(struct Client *client_p, int sendqex)
@@ -1209,7 +1268,7 @@ dead_link(struct Client *client_p, int sendqex)
        if(sendqex)
                rb_strlcpy(abt->notice, "Max SendQ exceeded", sizeof(abt->notice));
        else
-               rb_snprintf(abt->notice, sizeof(abt->notice), "Write error: %s", strerror(errno));
+               snprintf(abt->notice, sizeof(abt->notice), "Write error: %s", strerror(errno));
 
        abt->client = client_p;
        SetIOError(client_p);
@@ -1247,8 +1306,8 @@ exit_generic_client(struct Client *client_p, struct Client *source_p, struct Cli
        /* Clean up allow lists */
        del_all_accepts(source_p);
 
-       add_history(source_p, 0);
-       off_history(source_p);
+       whowas_add_history(source_p, 0);
+       whowas_off_history(source_p);
 
        monitor_signoff(source_p);
 
@@ -1291,15 +1350,22 @@ exit_remote_client(struct Client *client_p, struct Client *source_p, struct Clie
 }
 
 /*
- * This assumes IsUnknown(source_p) == TRUE and MyConnect(source_p) == TRUE
+ * This assumes IsUnknown(source_p) == true and MyConnect(source_p) == true
  */
 
 static int
-exit_unknown_client(struct Client *client_p, struct Client *source_p, struct Client *from,
-                 const char *comment)
+exit_unknown_client(struct Client *client_p, /* The local client originating the
+                                              * exit or NULL, if this exit is
+                                              * generated by this server for
+                                              * internal reasons.
+                                              * This will not get any of the
+                                              * generated messages. */
+               struct Client *source_p,     /* Client exiting */
+               struct Client *from,         /* Client firing off this Exit,
+                                              * never NULL! */
+               const char *comment)
 {
-       delete_auth_queries(source_p);
-       abort_blacklist_queries(source_p);
+       authd_abort_client(source_p);
        rb_dlinkDelete(&source_p->localClient->tnode, &unknown_list);
 
        if(!IsIOError(source_p))
@@ -1339,7 +1405,7 @@ exit_remote_server(struct Client *client_p, struct Client *source_p, struct Clie
                strcat(comment1, source_p->name);
        }
        if (IsPerson(from))
-               rb_snprintf(newcomment, sizeof(newcomment), "by %s: %s",
+               snprintf(newcomment, sizeof(newcomment), "by %s: %s",
                                from->name, comment);
 
        if(source_p->serv != NULL)
@@ -1417,7 +1483,7 @@ exit_local_server(struct Client *client_p, struct Client *source_p, struct Clien
        /* Always show source here, so the server notices show
         * which side initiated the split -- jilles
         */
-       rb_snprintf(newcomment, sizeof(newcomment), "by %s: %s",
+       snprintf(newcomment, sizeof(newcomment), "by %s: %s",
                        from == source_p ? me.name : from->name, comment);
        if (!IsIOError(source_p))
                sendto_one(source_p, "SQUIT %s :%s", use_id(source_p),
@@ -1469,7 +1535,7 @@ exit_local_server(struct Client *client_p, struct Client *source_p, struct Clien
 
 
 /*
- * This assumes IsPerson(source_p) == TRUE && MyConnect(source_p) == TRUE
+ * This assumes IsPerson(source_p) == true && MyConnect(source_p) == true
  */
 
 static int
@@ -1544,7 +1610,7 @@ exit_local_client(struct Client *client_p, struct Client *source_p, struct Clien
 **
 **        CLIENT_EXITED        if (client_p == source_p)
 **        0                if (client_p != source_p)
-*/
+ */
 int
 exit_client(struct Client *client_p,   /* The local client originating the
                                         * exit or NULL, if this exit is
@@ -1805,15 +1871,15 @@ free_user(struct User *user, struct Client *client_p)
                if(user->refcnt < 0 || user->invited.head || user->channel.head)
                {
                        sendto_realops_snomask(SNO_GENERAL, L_ALL,
-                                            "* %#lx user (%s!%s@%s) %#lx %#lx %#lx %lu %d *",
-                                            (unsigned long) client_p,
+                                            "* %p user (%s!%s@%s) %p %p %p %lu %d *",
+                                            client_p,
                                             client_p ? client_p->
                                             name : "<noname>",
                                             client_p->username,
                                             client_p->host,
-                                            (unsigned long) user,
-                                            (unsigned long) user->invited.head,
-                                            (unsigned long) user->channel.head,
+                                            user,
+                                            user->invited.head,
+                                            user->channel.head,
                                             rb_dlink_list_length(&user->channel),
                                             user->refcnt);
                        s_assert(!user->refcnt);
@@ -1860,19 +1926,21 @@ init_uid(void)
 char *
 generate_uid(void)
 {
+       static int flipped = 0;
        int i;
 
+uid_restart:
        for(i = 8; i > 3; i--)
        {
                if(current_uid[i] == 'Z')
                {
                        current_uid[i] = '0';
-                       return current_uid;
+                       goto out;
                }
                else if(current_uid[i] != '9')
                {
                        current_uid[i]++;
-                       return current_uid;
+                       goto out;
                }
                else
                        current_uid[i] = 'A';
@@ -1882,11 +1950,18 @@ generate_uid(void)
        if(current_uid[3] == 'Z')
        {
                current_uid[i] = 'A';
-               s_assert(0);
+               flipped = 1;
        }
        else
                current_uid[i]++;
-
+out:
+       /* if this happens..well, i'm not sure what to say, but lets handle it correctly */
+       if(rb_unlikely(flipped))
+       {
+               /* this slows down uid generation a bit... */
+               if(find_id(current_uid) != NULL)
+                       goto uid_restart;
+       }
        return current_uid;
 }
 
@@ -1944,13 +2019,14 @@ close_connection(struct Client *client_p)
        else
                ServerStats.is_ni++;
 
+       client_release_connids(client_p);
+
        if(client_p->localClient->F != NULL)
        {
                /* attempt to flush any pending dbufs. Evil, but .. -- adrian */
                if(!IsIOError(client_p))
                        send_queued(client_p);
 
-               del_from_cli_connid_hash(client_p);
                rb_close(client_p->localClient->F);
                client_p->localClient->F = NULL;
        }
@@ -2010,7 +2086,7 @@ error_exit_client(struct Client *client_p, int error)
        if(error == 0)
                rb_strlcpy(errmsg, "Remote host closed the connection", sizeof(errmsg));
        else
-               rb_snprintf(errmsg, sizeof(errmsg), "Read error: %s", strerror(current_error));
+               snprintf(errmsg, sizeof(errmsg), "Read error: %s", strerror(current_error));
 
        exit_client(client_p, client_p, &me, errmsg);
 }