]> source.dussan.org Git - rspamd.git/commitdiff
Add fuzzy stat implementation
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 14 Dec 2015 16:08:00 +0000 (16:08 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 14 Dec 2015 16:08:00 +0000 (16:08 +0000)
src/fuzzy_storage.c

index e0b336415946b61ed20895c636a94d5b0328d82b..50aff7141ce57c99a23645270a3728ec9953cb7c 100644 (file)
@@ -757,6 +757,134 @@ rspamd_fuzzy_storage_reload (struct rspamd_main *rspamd_main,
        return TRUE;
 }
 
+static ucl_object_t *
+rspamd_fuzzy_storage_stat_key (struct fuzzy_key_stat *key_stat)
+{
+       ucl_object_t *res;
+
+       res = ucl_object_typed_new (UCL_OBJECT);
+
+       ucl_object_insert_key (res, ucl_object_fromint (key_stat->checked),
+                       "checked", 0, false);
+       ucl_object_insert_key (res, ucl_object_fromint (key_stat->matched),
+                       "matched", 0, false);
+       ucl_object_insert_key (res, ucl_object_fromint (key_stat->added),
+                       "added", 0, false);
+       ucl_object_insert_key (res, ucl_object_fromint (key_stat->deleted),
+                       "deleted", 0, false);
+       ucl_object_insert_key (res, ucl_object_fromint (key_stat->errors),
+                       "errors", 0, false);
+
+       return res;
+}
+
+static gboolean
+rspamd_fuzzy_storage_stat (struct rspamd_main *rspamd_main,
+               struct rspamd_worker *worker, gint fd,
+               struct rspamd_control_command *cmd,
+               gpointer ud)
+{
+       struct rspamd_fuzzy_storage_ctx *ctx = ud;
+       struct rspamd_control_reply rep;
+       GHashTableIter it, ip_it;
+       GHashTable *ip_hash;
+       struct fuzzy_key_stat *key_stat;
+       struct rspamd_http_keypair *kp;
+       ucl_object_t *obj, *elt, *ip_elt, *ip_cur;
+       struct ucl_emitter_functions *emit_subr;
+       guchar fdspace[CMSG_SPACE(sizeof (int))];
+       struct iovec iov;
+       struct msghdr msg;
+       struct cmsghdr *cmsg;
+       gpointer k, v;
+       gint outfd = -1;
+       gchar tmppath[PATH_MAX], keyname[17];
+
+       memset (&rep, 0, sizeof (rep));
+       rep.type = RSPAMD_CONTROL_RELOAD;
+
+       rspamd_snprintf (tmppath, sizeof (tmppath), "%s%c%s-XXXXXXXXXX",
+                       rspamd_main->cfg->temp_dir, G_DIR_SEPARATOR, "fuzzy-stat");
+
+       if ((outfd = mkstemp (tmppath)) == -1) {
+               rep.reply.fuzzy_stat.status = errno;
+               msg_info_main ("cannot make temporary stat file for fuzzy stat: %s",
+                       strerror (errno));
+       }
+       else {
+               rep.reply.fuzzy_stat.status = 0;
+
+               /* Iterate over all keys */
+               obj = ucl_object_typed_new (UCL_OBJECT);
+               g_hash_table_iter_init (&it, ctx->keys);
+
+               while (g_hash_table_iter_next (&it, &k, &v)) {
+                       kp = v;
+                       key_stat = g_hash_table_lookup (ctx->keys_stats, kp->pk);
+
+                       if (key_stat) {
+                               rspamd_snprintf (keyname, sizeof (keyname), "%8xs", k);
+
+                               elt = rspamd_fuzzy_storage_stat_key (key_stat);
+
+                               if (key_stat->last_ips) {
+                                       ip_hash = rspamd_lru_hash_get_htable (key_stat->last_ips);
+
+                                       if (ip_hash) {
+                                               g_hash_table_iter_init (&ip_it, ip_hash);
+                                               ip_elt = ucl_object_typed_new (UCL_OBJECT);
+
+                                               while (g_hash_table_iter_next (&ip_it, &k, &v)) {
+                                                       ip_cur = rspamd_fuzzy_storage_stat_key (v);
+                                                       ucl_object_insert_key (ip_elt, ip_cur,
+                                                                       rspamd_inet_address_to_string (k), 0, true);
+                                               }
+
+                                               ucl_object_insert_key (elt, ip_elt, "ips", 0, false);
+                                       }
+                               }
+
+                               ucl_object_insert_key (obj, elt, keyname, 0, true);
+                       }
+               }
+
+               emit_subr = ucl_object_emit_fd_funcs (outfd);
+               ucl_object_emit_full (obj, UCL_EMIT_JSON_COMPACT, emit_subr);
+               ucl_object_emit_funcs_free (emit_subr);
+               ucl_object_unref (obj);
+       }
+
+       /* Now we can send outfd and status message */
+       memset (&msg, 0, sizeof (msg));
+
+       /* Attach fd to the message */
+       if (outfd != -1) {
+               memset (fdspace, 0, sizeof (fdspace));
+               msg.msg_control = fdspace;
+               msg.msg_controllen = sizeof (fdspace);
+               cmsg = CMSG_FIRSTHDR (&msg);
+               cmsg->cmsg_level = SOL_SOCKET;
+               cmsg->cmsg_type = SCM_RIGHTS;
+               cmsg->cmsg_len = CMSG_LEN (sizeof (int));
+               memcpy (CMSG_DATA (cmsg), &outfd, sizeof (int));
+       }
+
+       iov.iov_base = &rep;
+       iov.iov_len = sizeof (rep);
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
+
+       if (sendmsg (fd, &msg, 0) == -1) {
+               msg_err_main ("cannot send fuzzy stat: %s", strerror (errno));
+       }
+
+       if (outfd != -1) {
+               close (outfd);
+       }
+
+       return TRUE;
+}
+
 static gboolean
 fuzzy_parse_keypair (rspamd_mempool_t *pool,
                const ucl_object_t *obj,
@@ -1000,9 +1128,11 @@ start_fuzzy (struct rspamd_worker *worker)
                rspamd_fuzzy_backend_sync (ctx->backend, ctx->expire, TRUE);
        }
 
-       /* Register custom reload command for the control socket */
+       /* Register custom reload and stat commands for the control socket */
        rspamd_control_worker_add_cmd_handler (worker, RSPAMD_CONTROL_RELOAD,
                        rspamd_fuzzy_storage_reload, ctx);
+       rspamd_control_worker_add_cmd_handler (worker, RSPAMD_CONTROL_FUZZY_STAT,
+                       rspamd_fuzzy_storage_stat, ctx);
        /* Create radix tree */
        if (ctx->update_map != NULL) {
                if (!rspamd_map_add (worker->srv->cfg, ctx->update_map,