[master] 5cb857197 vmod_debug: split filter sources from rest of the code
Nils Goroll
nils.goroll at uplex.de
Mon Oct 7 16:03:05 UTC 2024
commit 5cb857197d471b4ccb175978b269441e25316dfc
Author: Nils Goroll <nils.goroll at uplex.de>
Date: Mon Oct 7 17:51:19 2024 +0200
vmod_debug: split filter sources from rest of the code
and flexelint
diff --git a/vmod/automake_boilerplate_debug.am b/vmod/automake_boilerplate_debug.am
index abda2454e..f2f2e36ad 100644
--- a/vmod/automake_boilerplate_debug.am
+++ b/vmod/automake_boilerplate_debug.am
@@ -10,6 +10,7 @@ libvmod_debug_la_SOURCES = \
vmod_debug.c \
vmod_debug_acl.c \
vmod_debug_dyn.c \
+ vmod_debug_filters.c \
vmod_debug_obj.c
libvmod_debug_la_CFLAGS =
diff --git a/vmod/flint.sh b/vmod/flint.sh
index 19053bcae..7ad9deeb0 100644
--- a/vmod/flint.sh
+++ b/vmod/flint.sh
@@ -10,6 +10,6 @@ for vmod in vmod_*.vcc ; do
echo "${vmod}"
echo "====================="
vmod="${vmod#vmod_}"
- FLOPS="-I../bin/varnishd vcc_${vmod}_if.c vmod_${vmod}*.c" \
+ FLOPS="-I../bin/varnishd -I../lib/libvgz vcc_${vmod}_if.c vmod_${vmod}*.c" \
../tools/flint_skel.sh
done
diff --git a/vmod/vmod_debug.c b/vmod/vmod_debug.c
index 1ced99c23..259497f8d 100644
--- a/vmod/vmod_debug.c
+++ b/vmod/vmod_debug.c
@@ -40,14 +40,14 @@
#include "cache/cache_filter.h"
#include "vsa.h"
-#include "vgz.h"
-#include "vsha256.h"
#include "vss.h"
#include "vtcp.h"
#include "vtim.h"
#include "vcc_debug_if.h"
#include "VSC_debug.h"
+#include "vmod_debug.h"
+
struct priv_vcl {
unsigned magic;
#define PRIV_VCL_MAGIC 0x8E62FA9D
@@ -74,584 +74,6 @@ extern void mylog(struct vsl_log *vsl, enum VSL_tag_e tag,
/**********************************************************************/
-static enum vfp_status v_matchproto_(vfp_pull_f)
-xyzzy_vfp_rot13_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
- ssize_t *lp)
-{
- enum vfp_status vp;
- char *q;
- ssize_t l;
-
- (void)vfe;
- vp = VFP_Suck(vc, p, lp);
- if (vp == VFP_ERROR)
- return (vp);
- q = p;
- for (l = 0; l < *lp; l++, q++) {
- if (*q >= 'A' && *q <= 'Z')
- *q = (((*q - 'A') + 13) % 26) + 'A';
- if (*q >= 'a' && *q <= 'z')
- *q = (((*q - 'a') + 13) % 26) + 'a';
- }
- return (vp);
-}
-
-static const struct vfp xyzzy_vfp_rot13 = {
- .name = "rot13",
- .pull = xyzzy_vfp_rot13_pull,
-};
-
-/**********************************************************************/
-
-// deliberately fragmenting the stream to make testing more interesting
-#define ROT13_BUFSZ 8
-
-static int v_matchproto_(vdp_init_f)
-xyzzy_vdp_rot13_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
-{
-
- CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
- CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
- CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
- CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
- AN(vdc->clen);
-
- AN(priv);
-
- *priv = malloc(ROT13_BUFSZ);
- if (*priv == NULL)
- return (-1);
-
- return (0);
-}
-
-static int v_matchproto_(vdp_bytes_f)
-xyzzy_vdp_rot13_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
- const void *ptr, ssize_t len)
-{
- char *q;
- const char *pp;
- int i, j, retval = 0;
-
- CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
- AN(priv);
- AN(*priv);
- if (len <= 0)
- return (VDP_bytes(vdc, act, ptr, len));
- AN(ptr);
- if (act != VDP_END)
- act = VDP_FLUSH;
- q = *priv;
- pp = ptr;
-
- for (i = 0, j = 0; j < len; i++, j++) {
- if (pp[j] >= 'A' && pp[j] <= 'Z')
- q[i] = (((pp[j] - 'A') + 13) % 26) + 'A';
- else if (pp[j] >= 'a' && pp[j] <= 'z')
- q[i] = (((pp[j] - 'a') + 13) % 26) + 'a';
- else
- q[i] = pp[j];
- if (i == ROT13_BUFSZ - 1 && j < len - 1) {
- retval = VDP_bytes(vdc, VDP_FLUSH, q, ROT13_BUFSZ);
- if (retval != 0)
- return (retval);
- i = -1;
- }
- }
- if (i >= 0)
- retval = VDP_bytes(vdc, act, q, i);
- return (retval);
-}
-
-static int v_matchproto_(vdp_fini_f)
-xyzzy_vdp_rot13_fini(struct vdp_ctx *vdc, void **priv)
-{
- (void)vdc;
- AN(priv);
- free(*priv);
- *priv = NULL;
- return (0);
-}
-
-static const struct vdp xyzzy_vdp_rot13 = {
- .name = "rot13",
- .init = xyzzy_vdp_rot13_init,
- .bytes = xyzzy_vdp_rot13_bytes,
- .fini = xyzzy_vdp_rot13_fini,
-};
-
-/**********************************************************************
- * vdp debug_chunked: force http1 chunked encoding by removing the
- * Content-Length header
- *
- * this happens in a VDP because cnt_transmit() runs after VCL and
- * restores it
- */
-
-static int v_matchproto_(vdp_init_f)
-xyzzy_vdp_chunked_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
-{
-
- CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
- CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
- CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
- CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
- AN(vdc->clen);
- AN(priv);
-
- http_Unset(vdc->hp, H_Content_Length);
- *vdc->clen = -1;
-
- return (1);
-}
-
-static const struct vdp xyzzy_vdp_chunked = {
- .name = "debug.chunked",
- .init = xyzzy_vdp_chunked_init,
-};
-
-/**********************************************************************
- * pedantic tests of the VDP API:
- * - assert that we see a VDP_END
- * - assert that _fini gets called before the task ends
- *
- * note:
- * we could lookup our own vdpe in _fini and check for vdpe->end == VDP_END
- * yet that would cross the API
- */
-
-enum vdp_state_e {
- VDPS_NULL = 0,
- VDPS_INIT, // _init called
- VDPS_BYTES, // _bytes called act != VDP_END
- VDPS_END, // _bytes called act == VDP_END
- VDPS_FINI // _fini called
-};
-
-struct vdp_state_s {
- unsigned magic;
-#define VDP_STATE_MAGIC 0x57c8d309
- enum vdp_state_e state;
-};
-
-static void v_matchproto_(vmod_priv_fini_f)
-priv_pedantic_fini(VRT_CTX, void *priv)
-{
- struct vdp_state_s *vdps;
-
- CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
- CAST_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC);
-
- assert(vdps->state == VDPS_FINI);
-}
-
-static const struct vmod_priv_methods priv_pedantic_methods[1] = {{
- .magic = VMOD_PRIV_METHODS_MAGIC,
- .type = "debug_vdp_pedantic",
- .fini = priv_pedantic_fini
-}};
-
-static int v_matchproto_(vdp_init_f)
-xyzzy_pedantic_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
-{
- struct vdp_state_s *vdps;
- struct vmod_priv *p;
-
- CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
- CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
- CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
- CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
- AN(vdc->clen);
- AN(priv);
-
- WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_STATE_MAGIC);
- if (vdps == NULL)
- return (-1);
- assert(vdps->state == VDPS_NULL);
-
- p = VRT_priv_task(ctx, (void *)vdc);
- if (p == NULL)
- return (-1);
- p->priv = vdps;
- p->methods = priv_pedantic_methods;
-
- *priv = vdps;
-
- vdps->state = VDPS_INIT;
-
- return (0);
-}
-
-static int v_matchproto_(vdp_bytes_f)
-xyzzy_pedantic_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
- const void *ptr, ssize_t len)
-{
- struct vdp_state_s *vdps;
-
- CAST_OBJ_NOTNULL(vdps, *priv, VDP_STATE_MAGIC);
- assert(vdps->state >= VDPS_INIT);
- assert(vdps->state < VDPS_END);
-
- if (act == VDP_END)
- vdps->state = VDPS_END;
- else
- vdps->state = VDPS_BYTES;
-
- return (VDP_bytes(vdc, act, ptr, len));
-}
-
-static int v_matchproto_(vdp_fini_f)
-xyzzy_pedantic_fini(struct vdp_ctx *vdc, void **priv)
-{
- struct vdp_state_s *vdps;
-
- (void) vdc;
- AN(priv);
- if (*priv == NULL)
- return (0);
- CAST_OBJ_NOTNULL(vdps, *priv, VDP_STATE_MAGIC);
- assert(vdps->state == VDPS_INIT || vdps->state == VDPS_END);
- vdps->state = VDPS_FINI;
-
- *priv = NULL;
- return (0);
-}
-
-static const struct vdp xyzzy_vdp_pedantic = {
- .name = "debug.pedantic",
- .init = xyzzy_pedantic_init,
- .bytes = xyzzy_pedantic_bytes,
- .fini = xyzzy_pedantic_fini,
-};
-
-/**********************************************************************
- *
- * this trivial copy/paste/edit filter (of rot13) was specifically made for
- * someone who added a DBG_SLOW_BEREQ debug flag. It should actually be turned
- * in a proper "bandwidth control" filter, but that exceeds an evening's work,
- * so it's kept for later
- */
-
-static enum vfp_status v_matchproto_(vfp_pull_f)
-xyzzy_vfp_slow_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
- ssize_t *lp)
-{
-
- (void)vfe;
- VTIM_sleep(1.0);
- return (VFP_Suck(vc, p, lp));
-}
-
-static const struct vfp xyzzy_vfp_slow = {
- .name = "debug.slow",
- .pull = xyzzy_vfp_slow_pull,
-};
-
-/**********************************************************************/
-
-static int v_matchproto_(vdp_bytes_f)
-xyzzy_vdp_slow_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
- const void *ptr, ssize_t len)
-{
-
- (void)priv;
- VTIM_sleep(1.0);
- return (VDP_bytes(vdc, act, ptr, len));
-}
-
-static const struct vdp xyzzy_vdp_slow = {
- .name = "debug.slow",
- .bytes = xyzzy_vdp_slow_bytes
-};
-
-/*
- * checksum VDP:
- * test that the stream of bytes has a certain checksum and either log
- * or panic
- *
- * The sha256 and crc32 variants are basically identical, but the amount of
- * code does not justify generalizing. (slink)
- */
-
-enum vdp_chk_mode_e {
- VDP_CHK_INVAL = 0,
- VDP_CHK_LOG,
- VDP_CHK_PANIC,
- VDP_CHK_PANIC_UNLESS_ERROR
-};
-
-struct vdp_chksha256_cfg_s {
- unsigned magic;
-#define VDP_CHKSHA256_CFG_MAGIC 0x624f5b32
- enum vdp_chk_mode_e mode;
- unsigned char expected[VSHA256_DIGEST_LENGTH];
-};
-
-struct vdp_chkcrc32_cfg_s {
- unsigned magic;
-#define VDP_CHKCRC32_CFG_MAGIC 0x5a7a835c
- enum vdp_chk_mode_e mode;
- uint32_t expected;
-};
-
-struct vdp_chksha256_s {
- unsigned magic;
-#define VDP_CHKSHA256_MAGIC 0x6856e913
- unsigned called;
- size_t bytes;
- struct VSHA256Context cx[1];
- struct vdp_chksha256_cfg_s *cfg;
-};
-
-struct vdp_chkcrc32_s {
- unsigned magic;
-#define VDP_CHKCRC32_MAGIC 0x15c03d3c
- unsigned called;
- size_t bytes;
- uint32_t crc;
- struct vdp_chkcrc32_cfg_s *cfg;
-};
-
-;
-
-const void * const chksha256_priv_id = &chksha256_priv_id;
-const void * const chkcrc32_priv_id = &chkcrc32_priv_id;
-
-static int v_matchproto_(vdp_init_f)
-xyzzy_chksha256_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
-{
- struct vdp_chksha256_s *vdps;
- struct vmod_priv *p;
-
- CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
- CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
- CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
- CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
- AN(vdc->clen);
- AN(priv);
-
- WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKSHA256_MAGIC);
- if (vdps == NULL)
- return (-1);
- VSHA256_Init(vdps->cx);
-
- p = VRT_priv_task_get(ctx, chksha256_priv_id);
- if (p == NULL)
- return (-1);
-
- assert(p->len == sizeof(struct vdp_chksha256_cfg_s));
- CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKSHA256_CFG_MAGIC);
- *priv = vdps;
-
- return (0);
-}
-
-static int v_matchproto_(vdp_init_f)
-xyzzy_chkcrc32_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
-{
- struct vdp_chkcrc32_s *vdps;
- struct vmod_priv *p;
-
- CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
- CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
- CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
- CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
- AN(vdc->clen);
- AN(priv);
-
- WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKCRC32_MAGIC);
- if (vdps == NULL)
- return (-1);
- vdps->crc = crc32(0L, Z_NULL, 0);
-
- p = VRT_priv_task_get(ctx, chkcrc32_priv_id);
- if (p == NULL)
- return (-1);
-
- assert(p->len == sizeof(struct vdp_chkcrc32_cfg_s));
- CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKCRC32_CFG_MAGIC);
- *priv = vdps;
-
- return (0);
-}
-
-static int v_matchproto_(vdp_bytes_f)
-xyzzy_chksha256_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
- const void *ptr, ssize_t len)
-{
- struct vdp_chksha256_s *vdps;
-
- CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKSHA256_MAGIC);
- VSHA256_Update(vdps->cx, ptr, len);
- vdps->called++;
- vdps->bytes += len;
- return (VDP_bytes(vdc, act, ptr, len));
-}
-
-static int v_matchproto_(vdp_bytes_f)
-xyzzy_chkcrc32_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
- const void *ptr, ssize_t len)
-{
- struct vdp_chkcrc32_s *vdps;
-
- CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKCRC32_MAGIC);
- if (len > 0)
- vdps->crc = crc32(vdps->crc, ptr, len);
- vdps->called++;
- vdps->bytes += len;
- return (VDP_bytes(vdc, act, ptr, len));
-}
-
-static int v_matchproto_(vdp_fini_f)
-xyzzy_chksha256_fini(struct vdp_ctx *vdc, void **priv)
-{
- unsigned char digest[VSHA256_DIGEST_LENGTH];
- enum vdp_chk_mode_e mode;
- struct vdp_chksha256_s *vdps;
- struct vsb *vsb;
- int r;
-
- (void) vdc;
- AN(priv);
- if (*priv == NULL)
- return (0);
- CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKSHA256_MAGIC);
- *priv = NULL;
-
- VSHA256_Final(digest, vdps->cx);
- r = memcmp(digest, vdps->cfg->expected, sizeof digest);
- if (r == 0)
- return (0);
-
- mode = vdps->cfg->mode;
- if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
- mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
-
- if (mode == VDP_CHK_LOG) {
- VSLb(vdc->vsl, SLT_Debug, "sha256 checksum mismatch");
-
- vsb = VSB_new_auto();
- VSB_quote(vsb, digest, sizeof digest, VSB_QUOTE_HEX);
- AZ(VSB_finish(vsb));
- VSLb(vdc->vsl, SLT_Debug, "got: %s", VSB_data(vsb));
-
- VSB_clear(vsb);
- VSB_quote(vsb, vdps->cfg->expected, sizeof digest, VSB_QUOTE_HEX);
- AZ(VSB_finish(vsb));
- VSLb(vdc->vsl, SLT_Debug, "exp: %s", VSB_data(vsb));
- VSB_destroy(&vsb);
- }
- else if (mode == VDP_CHK_PANIC)
- WRONG("body checksum");
- else
- WRONG("mode");
-
- return (0);
-}
-
-static int v_matchproto_(vdp_fini_f)
-xyzzy_chkcrc32_fini(struct vdp_ctx *vdc, void **priv)
-{
- enum vdp_chk_mode_e mode;
- struct vdp_chkcrc32_s *vdps;
-
- (void) vdc;
- AN(priv);
- if (*priv == NULL)
- return (0);
- CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKCRC32_MAGIC);
- *priv = NULL;
-
- if (vdps->crc == vdps->cfg->expected)
- return (0);
-
- mode = vdps->cfg->mode;
- if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
- mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
-
- if (mode == VDP_CHK_LOG) {
- VSLb(vdc->vsl, SLT_Debug, "crc32 checksum mismatch");
- VSLb(vdc->vsl, SLT_Debug, "got: %08x", vdps->crc);
- VSLb(vdc->vsl, SLT_Debug, "exp: %08x", vdps->cfg->expected);
- }
- else if (mode == VDP_CHK_PANIC)
- WRONG("body checksum");
- else
- WRONG("mode");
-
- return (0);
-}
-
-static const struct vdp xyzzy_vdp_chksha256 = {
- .name = "debug.chksha256",
- .init = xyzzy_chksha256_init,
- .bytes = xyzzy_chksha256_bytes,
- .fini = xyzzy_chksha256_fini,
-};
-
-static const struct vdp xyzzy_vdp_chkcrc32 = {
- .name = "debug.chkcrc32",
- .init = xyzzy_chkcrc32_init,
- .bytes = xyzzy_chkcrc32_bytes,
- .fini = xyzzy_chkcrc32_fini,
-};
-
-#define chkcfg(ws, cfg, magic, id, mode_e) do { \
- struct vmod_priv *p = VRT_priv_task(ctx, id); \
- \
- XXXAN(p); \
- if (p->priv == NULL) { \
- p->priv = WS_Alloc(ws, sizeof *cfg); \
- p->len = sizeof *cfg; \
- } \
- cfg = p->priv; \
- INIT_OBJ(cfg, magic); \
- if (mode_e == VENUM(log)) \
- cfg->mode = VDP_CHK_LOG; \
- else if (mode_e == VENUM(panic)) \
- cfg->mode = VDP_CHK_PANIC; \
- else if (mode_e == VENUM(panic_unless_error)) \
- cfg->mode = VDP_CHK_PANIC_UNLESS_ERROR; \
- else \
- WRONG("mode_e"); \
-} while(0)
-
-VCL_VOID v_matchproto_(td_xyzzy_debug_chksha256)
-xyzzy_chksha256(VRT_CTX, VCL_BLOB blob, VCL_ENUM mode_e)
-{
- struct vdp_chksha256_cfg_s *cfg;
- size_t l;
-
- CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
- AN(blob);
- XXXAN(blob->blob);
- XXXAN(blob->len);
-
- chkcfg(ctx->ws, cfg, VDP_CHKSHA256_CFG_MAGIC, chksha256_priv_id, mode_e);
-
- l = blob->len;
- if (l > sizeof cfg->expected)
- l = sizeof cfg->expected;
- memcpy(cfg->expected, blob->blob, l);
-
-}
-
-VCL_VOID v_matchproto_(td_xyzzy_debug_chkcrc32)
-xyzzy_chkcrc32(VRT_CTX, VCL_INT expected, VCL_ENUM mode_e)
-{
- struct vdp_chkcrc32_cfg_s *cfg;
-
- CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
-
- chkcfg(ctx->ws, cfg, VDP_CHKCRC32_CFG_MAGIC, chkcrc32_priv_id, mode_e);
-
- if (expected < 0)
- expected = 0;
- cfg->expected = (uintmax_t)expected % UINT32_MAX;
-}
-
-/**********************************************************************/
-
VCL_STRING v_matchproto_(td_debug_author)
xyzzy_author(VRT_CTX, VCL_ENUM person, VCL_ENUM someone)
{
@@ -783,15 +205,6 @@ xyzzy_test_priv_vcl(VRT_CTX, struct vmod_priv *priv)
assert(!strncmp(priv_vcl->foo, t, l));
}
-VCL_VOID v_matchproto_(td_debug_rot104)
-xyzzy_rot104(VRT_CTX)
-{
-
- CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
- // This should fail
- AN(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13));
-}
-
VCL_VOID v_matchproto_(td_debug_rot52)
xyzzy_rot52(VRT_CTX, VCL_HTTP hp)
{
@@ -918,12 +331,7 @@ event_load(VRT_CTX, struct vmod_priv *priv)
priv->priv = priv_vcl;
priv->methods = priv_vcl_methods;
- AZ(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13));
- AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_pedantic));
- AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chunked));
- AZ(VRT_AddFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow));
- AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chksha256));
- AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chkcrc32));
+ debug_add_filters(ctx);
return (0);
}
@@ -1085,12 +493,7 @@ event_discard(VRT_CTX, void *priv)
AZ(ctx->msg);
- VRT_RemoveFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow);
- VRT_RemoveFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13);
- VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_pedantic);
- VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chunked);
- VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chksha256);
- VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chkcrc32);
+ debug_remove_filters(ctx);
if (--loads)
return (0);
diff --git a/vmod/vmod_debug.h b/vmod/vmod_debug.h
new file mode 100644
index 000000000..05093be07
--- /dev/null
+++ b/vmod/vmod_debug.h
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2012-2019 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* vmod_debug_filters.c */
+void
+debug_add_filters(VRT_CTX);
+void
+debug_remove_filters(VRT_CTX);
diff --git a/vmod/vmod_debug_filters.c b/vmod/vmod_debug_filters.c
new file mode 100644
index 000000000..dba6c4a68
--- /dev/null
+++ b/vmod/vmod_debug_filters.c
@@ -0,0 +1,655 @@
+/*-
+ * Copyright (c) 2012-2019 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "cache/cache_varnishd.h"
+#include "cache/cache_filter.h"
+
+#include "vgz.h"
+#include "vsha256.h"
+#include "vtim.h"
+#include "vcc_debug_if.h"
+
+#include "vmod_debug.h"
+
+/**********************************************************************/
+
+static enum vfp_status v_matchproto_(vfp_pull_f)
+xyzzy_vfp_rot13_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
+ ssize_t *lp)
+{
+ enum vfp_status vp;
+ char *q;
+ ssize_t l;
+
+ (void)vfe;
+ vp = VFP_Suck(vc, p, lp);
+ if (vp == VFP_ERROR)
+ return (vp);
+ q = p;
+ for (l = 0; l < *lp; l++, q++) {
+ if (*q >= 'A' && *q <= 'Z')
+ *q = (((*q - 'A') + 13) % 26) + 'A';
+ if (*q >= 'a' && *q <= 'z')
+ *q = (((*q - 'a') + 13) % 26) + 'a';
+ }
+ return (vp);
+}
+
+static const struct vfp xyzzy_vfp_rot13 = {
+ .name = "rot13",
+ .pull = xyzzy_vfp_rot13_pull,
+};
+
+/**********************************************************************/
+
+// deliberately fragmenting the stream to make testing more interesting
+#define ROT13_BUFSZ 8
+
+static int v_matchproto_(vdp_init_f)
+xyzzy_vdp_rot13_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
+{
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
+ CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
+ CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
+ AN(vdc->clen);
+
+ AN(priv);
+
+ *priv = malloc(ROT13_BUFSZ);
+ if (*priv == NULL)
+ return (-1);
+
+ return (0);
+}
+
+static int v_matchproto_(vdp_bytes_f)
+xyzzy_vdp_rot13_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
+ const void *ptr, ssize_t len)
+{
+ char *q;
+ const char *pp;
+ int i, j, retval = 0;
+
+ CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
+ AN(priv);
+ AN(*priv);
+ if (len <= 0)
+ return (VDP_bytes(vdc, act, ptr, len));
+ AN(ptr);
+ if (act != VDP_END)
+ act = VDP_FLUSH;
+ q = *priv;
+ pp = ptr;
+
+ for (i = 0, j = 0; j < len; i++, j++) {
+ if (pp[j] >= 'A' && pp[j] <= 'Z')
+ q[i] = (((pp[j] - 'A') + 13) % 26) + 'A';
+ else if (pp[j] >= 'a' && pp[j] <= 'z')
+ q[i] = (((pp[j] - 'a') + 13) % 26) + 'a';
+ else
+ q[i] = pp[j];
+ if (i == ROT13_BUFSZ - 1 && j < len - 1) {
+ retval = VDP_bytes(vdc, VDP_FLUSH, q, ROT13_BUFSZ);
+ if (retval != 0)
+ return (retval);
+ i = -1;
+ }
+ }
+ if (i >= 0)
+ retval = VDP_bytes(vdc, act, q, i);
+ return (retval);
+}
+
+static int v_matchproto_(vdp_fini_f)
+xyzzy_vdp_rot13_fini(struct vdp_ctx *vdc, void **priv)
+{
+ (void)vdc;
+ AN(priv);
+ free(*priv);
+ *priv = NULL;
+ return (0);
+}
+
+static const struct vdp xyzzy_vdp_rot13 = {
+ .name = "rot13",
+ .init = xyzzy_vdp_rot13_init,
+ .bytes = xyzzy_vdp_rot13_bytes,
+ .fini = xyzzy_vdp_rot13_fini,
+};
+
+VCL_VOID v_matchproto_(td_debug_rot104)
+xyzzy_rot104(VRT_CTX)
+{
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ // This should fail
+ AN(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13));
+}
+
+/**********************************************************************
+ * vdp debug_chunked: force http1 chunked encoding by removing the
+ * Content-Length header
+ *
+ * this happens in a VDP because cnt_transmit() runs after VCL and
+ * restores it
+ */
+
+static int v_matchproto_(vdp_init_f)
+xyzzy_vdp_chunked_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
+{
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
+ CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
+ CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
+ AN(vdc->clen);
+ AN(priv);
+
+ http_Unset(vdc->hp, H_Content_Length);
+ *vdc->clen = -1;
+
+ return (1);
+}
+
+static const struct vdp xyzzy_vdp_chunked = {
+ .name = "debug.chunked",
+ .init = xyzzy_vdp_chunked_init,
+};
+
+/**********************************************************************
+ * pedantic tests of the VDP API:
+ * - assert that we see a VDP_END
+ * - assert that _fini gets called before the task ends
+ *
+ * note:
+ * we could lookup our own vdpe in _fini and check for vdpe->end == VDP_END
+ * yet that would cross the API
+ */
+
+enum vdp_state_e {
+ VDPS_NULL = 0,
+ VDPS_INIT, // _init called
+ VDPS_BYTES, // _bytes called act != VDP_END
+ VDPS_END, // _bytes called act == VDP_END
+ VDPS_FINI // _fini called
+};
+
+struct vdp_state_s {
+ unsigned magic;
+#define VDP_STATE_MAGIC 0x57c8d309
+ enum vdp_state_e state;
+};
+
+static void v_matchproto_(vmod_priv_fini_f)
+priv_pedantic_fini(VRT_CTX, void *priv)
+{
+ struct vdp_state_s *vdps;
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ CAST_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC);
+
+ assert(vdps->state == VDPS_FINI);
+}
+
+static const struct vmod_priv_methods priv_pedantic_methods[1] = {{
+ .magic = VMOD_PRIV_METHODS_MAGIC,
+ .type = "debug_vdp_pedantic",
+ .fini = priv_pedantic_fini
+}};
+
+static int v_matchproto_(vdp_init_f)
+xyzzy_pedantic_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
+{
+ struct vdp_state_s *vdps;
+ struct vmod_priv *p;
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
+ CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
+ CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
+ AN(vdc->clen);
+ AN(priv);
+
+ WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_STATE_MAGIC);
+ if (vdps == NULL)
+ return (-1);
+ assert(vdps->state == VDPS_NULL);
+
+ p = VRT_priv_task(ctx, (void *)vdc);
+ if (p == NULL)
+ return (-1);
+ p->priv = vdps;
+ p->methods = priv_pedantic_methods;
+
+ *priv = vdps;
+
+ vdps->state = VDPS_INIT;
+
+ return (0);
+}
+
+static int v_matchproto_(vdp_bytes_f)
+xyzzy_pedantic_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
+ const void *ptr, ssize_t len)
+{
+ struct vdp_state_s *vdps;
+
+ CAST_OBJ_NOTNULL(vdps, *priv, VDP_STATE_MAGIC);
+ assert(vdps->state >= VDPS_INIT);
+ assert(vdps->state < VDPS_END);
+
+ if (act == VDP_END)
+ vdps->state = VDPS_END;
+ else
+ vdps->state = VDPS_BYTES;
+
+ return (VDP_bytes(vdc, act, ptr, len));
+}
+
+static int v_matchproto_(vdp_fini_f)
+xyzzy_pedantic_fini(struct vdp_ctx *vdc, void **priv)
+{
+ struct vdp_state_s *vdps;
+
+ (void) vdc;
+ AN(priv);
+ if (*priv == NULL)
+ return (0);
+ CAST_OBJ_NOTNULL(vdps, *priv, VDP_STATE_MAGIC);
+ assert(vdps->state == VDPS_INIT || vdps->state == VDPS_END);
+ vdps->state = VDPS_FINI;
+
+ *priv = NULL;
+ return (0);
+}
+
+static const struct vdp xyzzy_vdp_pedantic = {
+ .name = "debug.pedantic",
+ .init = xyzzy_pedantic_init,
+ .bytes = xyzzy_pedantic_bytes,
+ .fini = xyzzy_pedantic_fini,
+};
+
+/**********************************************************************
+ *
+ * this trivial copy/paste/edit filter (of rot13) was specifically made for
+ * someone who added a DBG_SLOW_BEREQ debug flag. It should actually be turned
+ * in a proper "bandwidth control" filter, but that exceeds an evening's work,
+ * so it's kept for later
+ */
+
+static enum vfp_status v_matchproto_(vfp_pull_f)
+xyzzy_vfp_slow_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
+ ssize_t *lp)
+{
+
+ (void)vfe;
+ VTIM_sleep(1.0);
+ return (VFP_Suck(vc, p, lp));
+}
+
+static const struct vfp xyzzy_vfp_slow = {
+ .name = "debug.slow",
+ .pull = xyzzy_vfp_slow_pull,
+};
+
+/**********************************************************************/
+
+static int v_matchproto_(vdp_bytes_f)
+xyzzy_vdp_slow_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
+ const void *ptr, ssize_t len)
+{
+
+ (void)priv;
+ VTIM_sleep(1.0);
+ return (VDP_bytes(vdc, act, ptr, len));
+}
+
+static const struct vdp xyzzy_vdp_slow = {
+ .name = "debug.slow",
+ .bytes = xyzzy_vdp_slow_bytes
+};
+
+/*
+ * checksum VDP:
+ * test that the stream of bytes has a certain checksum and either log
+ * or panic
+ *
+ * The sha256 and crc32 variants are basically identical, but the amount of
+ * code does not justify generalizing. (slink)
+ */
+
+enum vdp_chk_mode_e {
+ //lint -esym(749, vdp_chk_mode_e::VDP_CHK_INVAL) deliberately not referenced
+ VDP_CHK_INVAL = 0,
+ VDP_CHK_LOG,
+ VDP_CHK_PANIC,
+ VDP_CHK_PANIC_UNLESS_ERROR
+};
+
+struct vdp_chksha256_cfg_s {
+ unsigned magic;
+#define VDP_CHKSHA256_CFG_MAGIC 0x624f5b32
+ enum vdp_chk_mode_e mode;
+ unsigned char expected[VSHA256_DIGEST_LENGTH];
+};
+
+struct vdp_chkcrc32_cfg_s {
+ unsigned magic;
+#define VDP_CHKCRC32_CFG_MAGIC 0x5a7a835c
+ enum vdp_chk_mode_e mode;
+ uint32_t expected;
+};
+
+struct vdp_chksha256_s {
+ unsigned magic;
+#define VDP_CHKSHA256_MAGIC 0x6856e913
+ unsigned called;
+ size_t bytes;
+ struct VSHA256Context cx[1];
+ struct vdp_chksha256_cfg_s *cfg;
+};
+
+struct vdp_chkcrc32_s {
+ unsigned magic;
+#define VDP_CHKCRC32_MAGIC 0x15c03d3c
+ unsigned called;
+ size_t bytes;
+ uint32_t crc;
+ struct vdp_chkcrc32_cfg_s *cfg;
+};
+
+static const void * const chksha256_priv_id = &chksha256_priv_id;
+static const void * const chkcrc32_priv_id = &chkcrc32_priv_id;
+
+static int v_matchproto_(vdp_init_f)
+xyzzy_chksha256_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
+{
+ struct vdp_chksha256_s *vdps;
+ struct vmod_priv *p;
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
+ CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
+ CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
+ AN(vdc->clen);
+ AN(priv);
+
+ WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKSHA256_MAGIC);
+ if (vdps == NULL)
+ return (-1);
+ VSHA256_Init(vdps->cx);
+
+ p = VRT_priv_task_get(ctx, chksha256_priv_id);
+ if (p == NULL)
+ return (-1);
+
+ assert(p->len == sizeof(struct vdp_chksha256_cfg_s));
+ CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKSHA256_CFG_MAGIC);
+ *priv = vdps;
+
+ return (0);
+}
+
+static int v_matchproto_(vdp_init_f)
+xyzzy_chkcrc32_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
+{
+ struct vdp_chkcrc32_s *vdps;
+ struct vmod_priv *p;
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
+ CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
+ CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
+ AN(vdc->clen);
+ AN(priv);
+
+ WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKCRC32_MAGIC);
+ if (vdps == NULL)
+ return (-1);
+ vdps->crc = crc32(0L, Z_NULL, 0);
+
+ p = VRT_priv_task_get(ctx, chkcrc32_priv_id);
+ if (p == NULL)
+ return (-1);
+
+ assert(p->len == sizeof(struct vdp_chkcrc32_cfg_s));
+ CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKCRC32_CFG_MAGIC);
+ *priv = vdps;
+
+ return (0);
+}
+
+static int v_matchproto_(vdp_bytes_f)
+xyzzy_chksha256_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
+ const void *ptr, ssize_t len)
+{
+ struct vdp_chksha256_s *vdps;
+
+ CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKSHA256_MAGIC);
+ VSHA256_Update(vdps->cx, ptr, len);
+ vdps->called++;
+ vdps->bytes += len;
+ return (VDP_bytes(vdc, act, ptr, len));
+}
+
+static int v_matchproto_(vdp_bytes_f)
+xyzzy_chkcrc32_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
+ const void *ptr, ssize_t len)
+{
+ struct vdp_chkcrc32_s *vdps;
+
+ CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKCRC32_MAGIC);
+ if (len > 0)
+ vdps->crc = crc32(vdps->crc, ptr, len);
+ vdps->called++;
+ vdps->bytes += len;
+ return (VDP_bytes(vdc, act, ptr, len));
+}
+
+static int v_matchproto_(vdp_fini_f)
+xyzzy_chksha256_fini(struct vdp_ctx *vdc, void **priv)
+{
+ unsigned char digest[VSHA256_DIGEST_LENGTH];
+ enum vdp_chk_mode_e mode;
+ struct vdp_chksha256_s *vdps;
+ struct vsb *vsb;
+ int r;
+
+ (void) vdc;
+ AN(priv);
+ if (*priv == NULL)
+ return (0);
+ CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKSHA256_MAGIC);
+ *priv = NULL;
+
+ VSHA256_Final(digest, vdps->cx);
+ r = memcmp(digest, vdps->cfg->expected, sizeof digest);
+ if (r == 0)
+ return (0);
+
+ mode = vdps->cfg->mode;
+ if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
+ mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
+
+ if (mode == VDP_CHK_LOG) {
+ VSLb(vdc->vsl, SLT_Debug, "sha256 checksum mismatch");
+
+ vsb = VSB_new_auto();
+ VSB_quote(vsb, digest, sizeof digest, VSB_QUOTE_HEX);
+ AZ(VSB_finish(vsb));
+ VSLb(vdc->vsl, SLT_Debug, "got: %s", VSB_data(vsb));
+
+ VSB_clear(vsb);
+ VSB_quote(vsb, vdps->cfg->expected, sizeof digest, VSB_QUOTE_HEX);
+ AZ(VSB_finish(vsb));
+ VSLb(vdc->vsl, SLT_Debug, "exp: %s", VSB_data(vsb));
+ VSB_destroy(&vsb);
+ }
+ else if (mode == VDP_CHK_PANIC)
+ WRONG("body checksum");
+ else
+ WRONG("mode");
+
+ return (0);
+}
+
+static int v_matchproto_(vdp_fini_f)
+xyzzy_chkcrc32_fini(struct vdp_ctx *vdc, void **priv)
+{
+ enum vdp_chk_mode_e mode;
+ struct vdp_chkcrc32_s *vdps;
+
+ (void) vdc;
+ AN(priv);
+ if (*priv == NULL)
+ return (0);
+ CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKCRC32_MAGIC);
+ *priv = NULL;
+
+ if (vdps->crc == vdps->cfg->expected)
+ return (0);
+
+ mode = vdps->cfg->mode;
+ if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
+ mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
+
+ if (mode == VDP_CHK_LOG) {
+ VSLb(vdc->vsl, SLT_Debug, "crc32 checksum mismatch");
+ VSLb(vdc->vsl, SLT_Debug, "got: %08x", vdps->crc);
+ VSLb(vdc->vsl, SLT_Debug, "exp: %08x", vdps->cfg->expected);
+ }
+ else if (mode == VDP_CHK_PANIC)
+ WRONG("body checksum");
+ else
+ WRONG("mode");
+
+ return (0);
+}
+
+static const struct vdp xyzzy_vdp_chksha256 = {
+ .name = "debug.chksha256",
+ .init = xyzzy_chksha256_init,
+ .bytes = xyzzy_chksha256_bytes,
+ .fini = xyzzy_chksha256_fini,
+};
+
+static const struct vdp xyzzy_vdp_chkcrc32 = {
+ .name = "debug.chkcrc32",
+ .init = xyzzy_chkcrc32_init,
+ .bytes = xyzzy_chkcrc32_bytes,
+ .fini = xyzzy_chkcrc32_fini,
+};
+
+#define chkcfg(ws, cfg, magic, id, mode_e) do { \
+ struct vmod_priv *p = VRT_priv_task(ctx, id); \
+ \
+ XXXAN(p); \
+ if (p->priv == NULL) { \
+ p->priv = WS_Alloc(ws, sizeof *cfg); \
+ p->len = sizeof *cfg; \
+ } \
+ cfg = p->priv; \
+ INIT_OBJ(cfg, magic); \
+ if (mode_e == VENUM(log)) \
+ cfg->mode = VDP_CHK_LOG; \
+ else if (mode_e == VENUM(panic)) \
+ cfg->mode = VDP_CHK_PANIC; \
+ else if (mode_e == VENUM(panic_unless_error)) \
+ cfg->mode = VDP_CHK_PANIC_UNLESS_ERROR; \
+ else \
+ WRONG("mode"); \
+} while(0)
+
+VCL_VOID v_matchproto_(td_xyzzy_debug_chksha256)
+xyzzy_chksha256(VRT_CTX, VCL_BLOB blob, VCL_ENUM mode_e)
+{
+ struct vdp_chksha256_cfg_s *cfg;
+ size_t l;
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ AN(blob);
+ XXXAN(blob->blob);
+ XXXAN(blob->len);
+
+ chkcfg(ctx->ws, cfg, VDP_CHKSHA256_CFG_MAGIC, chksha256_priv_id, mode_e);
+
+ l = blob->len;
+ if (l > sizeof cfg->expected)
+ l = sizeof cfg->expected;
+ memcpy(cfg->expected, blob->blob, l);
+
+}
+
+VCL_VOID v_matchproto_(td_xyzzy_debug_chkcrc32)
+xyzzy_chkcrc32(VRT_CTX, VCL_INT expected, VCL_ENUM mode_e)
+{
+ struct vdp_chkcrc32_cfg_s *cfg;
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+ chkcfg(ctx->ws, cfg, VDP_CHKCRC32_CFG_MAGIC, chkcrc32_priv_id, mode_e);
+
+ if (expected < 0)
+ expected = 0;
+ cfg->expected = (uintmax_t)expected % UINT32_MAX;
+}
+
+void
+debug_add_filters(VRT_CTX)
+{
+ AZ(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13));
+ AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_pedantic));
+ AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chunked));
+ AZ(VRT_AddFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow));
+ AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chksha256));
+ AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chkcrc32));
+}
+
+void
+debug_remove_filters(VRT_CTX)
+{
+ VRT_RemoveFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow);
+ VRT_RemoveFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13);
+ VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_pedantic);
+ VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chunked);
+ VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chksha256);
+ VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chkcrc32);
+}
More information about the varnish-commit
mailing list