/*
* 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();
}
syntax highlighted by Code2HTML, v. 0.9.1