]> jfr.im git - solanum.git/blobdiff - ircd/reject.c
whowas.c: store account name in whowas (#323)
[solanum.git] / ircd / reject.c
index 90f4f1e84075b8f622d770f06fee5ef8599b5137..db90d388a1e2efabda331414c3edd10719138419 100644 (file)
@@ -45,6 +45,8 @@ static void throttle_expires(void *unused);
 typedef struct _reject_data
 {
        rb_dlink_node rnode;
+       struct ConfItem *aconf;
+       const char *reason;
        time_t time;
        unsigned int count;
        uint32_t mask_hashv;
@@ -54,6 +56,8 @@ typedef struct _delay_data
 {
        rb_dlink_node node;
        rb_fde_t *F;
+       struct ConfItem *aconf;
+       const char *reason;
 } delay_t;
 
 typedef struct _throttle
@@ -69,9 +73,21 @@ delay_exit_length(void)
        return rb_dlink_list_length(&delay_exit);
 }
 
+static void
+reject_free(reject_t *rdata)
+{
+       struct ConfItem *aconf = rdata->aconf;
+
+       if (aconf)
+               deref_conf(aconf);
+
+       rb_free(rdata);
+}
+
 static void
 reject_exit(void *unused)
 {
+       static char dynamic_reason[BUFSIZE];
        rb_dlink_node *ptr, *ptr_next;
        delay_t *ddata;
        static const char *errbuf = "ERROR :Closing Link: (*** Banned (cache))\r\n";
@@ -80,6 +96,23 @@ reject_exit(void *unused)
        {
                ddata = ptr->data;
 
+               *dynamic_reason = '\0';
+
+               if (ddata->aconf)
+               {
+                       snprintf(dynamic_reason, BUFSIZE, form_str(ERR_YOUREBANNEDCREEP) "\r\n",
+                               me.name, "*", get_user_ban_reason(ddata->aconf));
+                       rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
+
+                       deref_conf(ddata->aconf);
+               }
+               else if (ddata->reason)
+               {
+                       snprintf(dynamic_reason, BUFSIZE, ":%s 465 %s :%s\r\n",
+                               me.name, "*", ddata->reason);
+                       rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
+               }
+
                rb_write(ddata->F, errbuf, strlen(errbuf));
                rb_close(ddata->F);
                rb_free(ddata);
@@ -105,7 +138,7 @@ reject_expires(void *unused)
                        continue;
 
                rb_dlinkDelete(ptr, &reject_list);
-               rb_free(rdata);
+               reject_free(rdata);
                rb_patricia_remove(reject_tree, pnode);
        }
 }
@@ -141,7 +174,7 @@ throttle_size(void)
 }
 
 void
-add_reject(struct Client *client_p, const char *mask1, const char *mask2)
+add_reject(struct Client *client_p, const char *mask1, const char *mask2, struct ConfItem *aconf, const char *reason)
 {
        rb_patricia_node_t *pnode;
        reject_t *rdata;
@@ -166,17 +199,32 @@ add_reject(struct Client *client_p, const char *mask1, const char *mask2)
        else
        {
                int bitlen = 32;
-#ifdef RB_IPV6
                if(GET_SS_FAMILY(&client_p->localClient->ip) == AF_INET6)
                        bitlen = 128;
-#endif
                pnode = make_and_lookup_ip(reject_tree, (struct sockaddr *)&client_p->localClient->ip, bitlen);
                pnode->data = rdata = rb_malloc(sizeof(reject_t));
                rb_dlinkAddTail(pnode, &rdata->rnode, &reject_list);
                rdata->time = rb_current_time();
                rdata->count = 1;
+               rdata->aconf = NULL;
+               rdata->reason = NULL;
        }
        rdata->mask_hashv = hashv;
+
+       if (aconf != NULL && aconf != rdata->aconf && (aconf->status & CONF_KILL) && aconf->passwd)
+       {
+               if (rdata->aconf != NULL)
+                       deref_conf(rdata->aconf);
+               aconf->clients++;
+               rdata->aconf = aconf;
+       }
+       else if (reason != NULL)
+       {
+               if (rdata->aconf != NULL)
+                       deref_conf(rdata->aconf);
+               rdata->aconf = NULL;
+               rdata->reason = reason;
+       }
 }
 
 int
@@ -185,28 +233,51 @@ check_reject(rb_fde_t *F, struct sockaddr *addr)
        rb_patricia_node_t *pnode;
        reject_t *rdata;
        delay_t *ddata;
+
        /* Reject is disabled */
-       if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
+       if (ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
                return 0;
 
        pnode = rb_match_ip(reject_tree, addr);
-       if(pnode != NULL)
+       if (pnode == NULL)
+               return 0;
+
+       rdata = pnode->data;
+       rdata->time = rb_current_time();
+
+       if (rdata->count <= (unsigned long)ConfigFileEntry.reject_after_count)
+               return 0;
+
+       if (rdata->aconf != NULL && rdata->aconf->status & CONF_ILLEGAL)
        {
-               rdata = pnode->data;
+               rb_dlinkDelete(&rdata->rnode, &reject_list);
+               reject_free(rdata);
+               rb_patricia_remove(reject_tree, pnode);
+               return 0;
+       }
 
-               rdata->time = rb_current_time();
-               if(rdata->count > (unsigned long)ConfigFileEntry.reject_after_count)
-               {
-                       ddata = rb_malloc(sizeof(delay_t));
-                       ServerStats.is_rej++;
-                       rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL);
-                       ddata->F = F;
-                       rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
-                       return 1;
-               }
+       ddata = rb_malloc(sizeof(delay_t));
+       ServerStats.is_rej++;
+       rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL);
+       if (rdata->aconf)
+       {
+               ddata->aconf = rdata->aconf;
+               ddata->aconf->clients++;
+               ddata->reason = NULL;
        }
-       /* Caller does what it wants */
-       return 0;
+       else if (rdata->reason)
+       {
+               ddata->reason = rdata->reason;
+               ddata->aconf = NULL;
+       }
+       else
+       {
+               ddata->aconf = NULL;
+               ddata->reason = NULL;
+       }
+       ddata->F = F;
+       rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
+       return 1;
 }
 
 int
@@ -246,7 +317,7 @@ flush_reject(void)
                pnode = ptr->data;
                rdata = pnode->data;
                rb_dlinkDelete(ptr, &reject_list);
-               rb_free(rdata);
+               reject_free(rdata);
                rb_patricia_remove(reject_tree, pnode);
        }
 }
@@ -264,7 +335,7 @@ remove_reject_ip(const char *ip)
        {
                reject_t *rdata = pnode->data;
                rb_dlinkDelete(&rdata->rnode, &reject_list);
-               rb_free(rdata);
+               reject_free(rdata);
                rb_patricia_remove(reject_tree, pnode);
                return 1;
        }
@@ -292,7 +363,7 @@ remove_reject_mask(const char *mask1, const char *mask2)
                if (rdata->mask_hashv == hashv)
                {
                        rb_dlinkDelete(ptr, &reject_list);
-                       rb_free(rdata);
+                       reject_free(rdata);
                        rb_patricia_remove(reject_tree, pnode);
                        n++;
                }
@@ -321,10 +392,8 @@ throttle_add(struct sockaddr *addr)
 
        } else {
                int bitlen = 32;
-#ifdef RB_IPV6
                if(GET_SS_FAMILY(addr) == AF_INET6)
                        bitlen = 128;
-#endif
                t = rb_malloc(sizeof(throttle_t));
                t->last = rb_current_time();
                t->count = 1;