/* * Copyright (c) 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: t-greyctl-0.c,v 1.6 2006/12/01 16:54:53 ca Exp $") #include "sm/assert.h" #include "sm/error.h" #include "sm/types.h" #include "sm/net.h" #include "sm/greyctl.h" #include "sm/greycnf.h" #include "sm/io.h" #include "sm/test.h" #include "greyctl.h" static int Verbose = 0; static sm_ret_T grey_display1(DB *db, DB *sdb, sm_file_T *fp) { sm_ret_T ret; DBC *dbcp; DBT db_data, db_key; greyentry_T ge; bool first; ret = db->cursor(sdb, NULL, &dbcp, 0); if (ret != 0) return ret; first = true; do { sm_memzero(&db_key, sizeof(db_key)); sm_memzero(&db_data, sizeof(db_data)); db_data.flags = DB_DBT_USERMEM; db_data.data = ≥ db_data.ulen = sizeof(ge); ret = dbcp->c_get(dbcp, &db_key, &db_data, first ? DB_FIRST : DB_NEXT); if (0 == ret) { sm_io_fprintf(fp, "addr=%16A, time=%7ld, expire=%7ld, type=%s\n", (ipv4_T) ge.ge_key, (long) ge.ge_time, (long) ge.ge_expire, ge.ge_type == GREY_TYPE_GREY ? "grey" : ge.ge_type == GREY_TYPE_WHITE ? "white" : "oops"); } first = false; } while (0 == ret); ret = dbcp->c_close(dbcp); return ret; } static sm_ret_T grey_display(greyctx_P greyctx, sm_file_T *fp) { sm_ret_T ret; ret = grey_display1(greyctx->greyc_grey_db, greyctx->greyc_grey_sdb, fp); sm_io_putc(fp, '\n'); sm_io_flush(fp); return ret; } static sm_ret_T grey_display0(DB *db, sm_file_T *fp) { sm_ret_T ret; DBC *dbcp; DBT db_data, db_key; greyentry_T ge; ret = db->cursor(db, NULL, &dbcp, 0); if (ret != 0) return ret; do { sm_memzero(&db_key, sizeof(db_key)); sm_memzero(&db_data, sizeof(db_data)); db_data.flags = DB_DBT_USERMEM; db_data.data = ≥ db_data.ulen = sizeof(ge); ret = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT); if (0 == ret) { sm_io_fprintf(fp, "addr=%16A, time=%7ld, expire=%7ld, type=%s\n", (ipv4_T) ge.ge_key, (long) ge.ge_time, (long) ge.ge_expire, ge.ge_type == GREY_TYPE_GREY ? "grey" : ge.ge_type == GREY_TYPE_WHITE ? "white" : "oops"); } } while (0 == ret); ret = dbcp->c_close(dbcp); return ret; } static sm_ret_T grey_display_m(greyctx_P greyctx, sm_file_T *fp) { sm_ret_T ret; ret = grey_display0(greyctx->greyc_grey_db, fp); sm_io_putc(fp, '\n'); sm_io_flush(fp); return ret; } static void testg(bool display, bool display_m) { sm_ret_T ret; uint ht_size, ht_limit, ge_limit, u, off; ipv4_T addr, grey_ip1, grey_ip2; time_t t; greyctx_P greyctx; #define T_GREY_MIN_WAIT 60 #define T_GREY_MAX_WAIT 600 #define T_WHITE_EXP 6000 #define T_WHITE_TMO 12000 #define T_GREY_IP1 1 #define T_GREY_IP2 2 ht_size = 31; ht_limit = 16; ge_limit = 8; ret = sm_greyctl_crt(&greyctx); SM_TEST(SM_SUCCESS == ret); if (ret != SM_SUCCESS) return; greyctx->greyc_cnf.greycnf_limit = ht_limit; greyctx->greyc_cnf.greycnf_min_grey_wait = T_GREY_MIN_WAIT; greyctx->greyc_cnf.greycnf_max_grey_wait = T_GREY_MAX_WAIT; greyctx->greyc_cnf.greycnf_white_expire = T_WHITE_EXP; greyctx->greyc_cnf.greycnf_white_reconfirm = T_WHITE_TMO; grey_ip1 = T_GREY_IP1; grey_ip2 = T_GREY_IP2; ret = sm_greyctl_open(greyctx, NULL); SM_TEST(SM_SUCCESS == ret); if (ret != SM_SUCCESS) return; if (display) { grey_display(greyctx, smioout); goto done; } if (display_m) { grey_display_m(greyctx, smioout); goto done; } t = 0; ret = sm_greyctl(greyctx, (uchar *)&grey_ip1, sizeof(ipv4_T), t + 1); SM_TEST(SM_GREY_FIRST == ret); ret = sm_greyctl(greyctx, (uchar *)&grey_ip2, sizeof(ipv4_T), t + 2); SM_TEST(SM_GREY_FIRST == ret); ret = sm_greyctl(greyctx, (uchar *)&grey_ip1, sizeof(ipv4_T), t + 10); SM_TEST(SM_GREY_WAIT == ret); ret = sm_greyctl(greyctx, (uchar *)&grey_ip1, sizeof(ipv4_T), t + T_GREY_MIN_WAIT - 1); SM_TEST(SM_GREY_WAIT == ret); ret = sm_greyctl(greyctx, (uchar *)&grey_ip1, sizeof(ipv4_T), t + T_GREY_MIN_WAIT); SM_TEST(SM_GREY_WAIT == ret); ret = sm_greyctl(greyctx, (uchar *)&grey_ip1, sizeof(ipv4_T), t + T_GREY_MIN_WAIT + 1); SM_TEST(SM_GREY_OK == ret); off = T_GREY_MIN_WAIT + 2; ret = sm_greyctl(greyctx, (uchar *)&grey_ip2, sizeof(ipv4_T), t + off); SM_TEST(SM_GREY_OK == ret); off += 10; ret = sm_greyctl(greyctx, (uchar *)&grey_ip2, sizeof(ipv4_T), t + off); SM_TEST(SM_GREY_OK == ret); off += 30; ret = sm_greyctl(greyctx, (uchar *)&grey_ip2, sizeof(ipv4_T), t + off); SM_TEST(SM_GREY_OK == ret); off += 90; ret = sm_greyctl(greyctx, (uchar *)&grey_ip2, sizeof(ipv4_T), t + off); SM_TEST(SM_GREY_OK == ret); ret = sm_greyctl(greyctx, (uchar *)&grey_ip2, sizeof(ipv4_T), t + off + T_WHITE_TMO + 3); SM_TEST(SM_GREY_AGAIN == ret); /* test overflow of hash table */ t = T_WHITE_TMO + T_WHITE_EXP + 10; for (u = 0; u < ht_limit; u++) { addr = u + 4; ret = sm_greyctl(greyctx, (uchar *)&addr, sizeof(addr), t + u); SM_TEST(SM_GREY_FIRST == ret); if (ret != SM_GREY_FIRST) sm_io_fprintf(smioerr, "u=%d, ret=%r\n", u, ret); } /* addr = u + 4; ret = sm_greyctl(greyctx, (uchar *)&addr, sizeof(addr), t + u); SM_TEST(sm_is_err(ret)); */ /* timeout: can add new entry */ u = ht_limit + 1; t += T_GREY_MAX_WAIT + 1 + u; addr = 4 + ht_limit + 1; ret = sm_greyctl(greyctx, (uchar *)&addr, sizeof(addr), t); SM_TEST(SM_GREY_FIRST == ret); t += T_GREY_MIN_WAIT; ret = sm_greyctl(greyctx, (uchar *)&addr, sizeof(addr), t); SM_TEST(SM_GREY_OK == ret); /* more tests??? */ if (Verbose > 0) grey_display(greyctx, smioout); done: ret = sm_greyctl_free(greyctx); SM_TEST(SM_SUCCESS == ret); } int main(int argc, char *argv[]) { int c; bool display, display_m; display = false; display_m = false; while ((c = getopt(argc, argv, "dmV")) != -1) { switch (c) { case 'd': display = true; break; case 'm': display_m = true; break; case 'V': ++Verbose; break; default: return(1); } } if (!(display || display_m)) { (void) unlink("grey_grey_m.db"); (void) unlink("grey_grey_s.db"); } sm_test_begin(argc, argv, "test greylist"); testg(display, display_m); return sm_test_end(); }