/*
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: t-greyctl-2.c,v 1.2 2007/02/14 03:34:24 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/types.h"
#include "sm/net.h"
#include "sm/greyctl.h"
#include "sm/io.h"
#include "sm/test.h"
#include "greyctl.h"
static int Verbose = 0;
#define KEYLEN GL_KEYLEN
static DBC *DBcursor;
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;
ipv4_T addr;
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 (ret == 0) {
SM_TEST_E(ge.ge_len > 4);
sm_memcpy(&addr, ge.ge_key, sizeof(addr));
sm_io_fprintf(fp,
"addr=%16A, mail/rcpt=%*s time=%7ld, expire=%7ld, type=%s\n",
addr, (int) ge.ge_len - 4, ge.ge_key + 4,
(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 (ret == 0);
error:
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
sm_grey_findprefix(DB *db, void *key, uint len, greyentry_P ge)
{
sm_ret_T ret;
DBT db_data, db_key;
uchar mykey[KEYLEN];
sm_memzero(&db_key, sizeof(db_key));
sm_memzero(&db_data, sizeof(db_data));
SM_REQUIRE(len < sizeof(mykey));
sm_memcpy(mykey, key, len);
db_key.data = mykey;
db_key.size = len;
db_key.ulen = sizeof(mykey);
db_data.flags = DB_DBT_USERMEM;
db_data.data = ge;
db_data.ulen = sizeof(*ge);
/*
ret = db->get(db, NULL, &db_key, &db_data, DB_SET_RANGE);
*/
ret = DBcursor->c_get(DBcursor,&db_key, &db_data, DB_SET_RANGE);
SM_TEST(0 == ret);
sm_io_fprintf(smioerr, "get_prefix=%d\n", ret);
return ret;
}
static void
testg(uint entries, uint ips, bool display)
{
sm_ret_T ret;
uint ht_size, ht_limit, ge_limit, u;
int r;
uchar **keys, *key;
uint *keylens;
time_t t;
greyctx_P greyctx;
time_t start, elapsed;
uint greyr[2];
greyentry_T ges;
greyentry_P ge;
#define T_GREY_MIN_WAIT 60
#define T_GREY_MAX_WAIT 600
#define T_WHITE_EXP 6000
#define T_WHITE_TMO 12000
ht_size = 40000;
ht_limit = 40000;
ge_limit = 20000;
keys = (uchar **) sm_malloc(ips * sizeof(*keys));
SM_TEST_E(keys != NULL);
keylens = (uint *) sm_malloc(ips * sizeof(*keylens));
SM_TEST_E(keylens != NULL);
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;
ret = sm_greyctl_open(greyctx, NULL);
SM_TEST(SM_SUCCESS == ret);
if (ret != SM_SUCCESS)
return;
srand(1);
for (u = 0; u < ips; u++) {
key = (uchar *) sm_malloc(KEYLEN);
SM_TEST_E(key != NULL);
r = sm_snprintf((char *)key, KEYLEN,
"%c%c%c%c<sender%d@domain-%d.tld><rcpt+%d@other-domain-%d.invalid>"
, (char) rand(), (char) rand(), (char) rand(), (char) rand()
, rand(), rand(), rand(), rand());
SM_TEST_E(r < KEYLEN);
keys[u] = key;
keylens[u] = r;
if (Verbose > 2) {
sm_io_fprintf(smioerr, "key[%d], len=%u, %s\n", u, r, key + 4);
}
}
greyr[0] = 0;
greyr[1] = 0;
start = time((time_t *) 0);
t = 1;
for (u = 0; u < entries; u++)
{
key = keys[u % ips];
ret = sm_greyctl(greyctx, key, keylens[u % ips], t + u);
if (Verbose > 1) {
sm_io_fprintf(smioerr, "key[%d] %s, ret=%#x\n", u % ips, key + 4, ret);
}
switch (ret)
{
case SM_GREY_AGAIN:
case SM_GREY_FIRST:
case SM_GREY_WAIT:
++greyr[1];
break;
case SM_GREY_OK:
++greyr[0];
break;
default:
goto done;
}
}
elapsed = time((time_t *) 0) - start;
sm_io_fprintf(smioout, "elapsed time: %ld\n", (long) elapsed);
if (elapsed > 0)
sm_io_fprintf(smioout, "updates/s: %ld\n", (long) entries / elapsed);
sm_io_fprintf(smioout, "wait=%u\nok= %u\n", greyr[1], greyr[0]);
if (display)
grey_display(greyctx, smioout);
sm_io_flush(smioout);
ge = ⩾
key = keys[0];
ret = greyctx->greyc_grey_db->cursor(greyctx->greyc_grey_db, NULL, &DBcursor, 0);
SM_TEST_E(0 == ret);
ret = sm_grey_findprefix(greyctx->greyc_grey_db, key, 4, ge);
SM_TEST_E(0 == ret);
done:
ret = sm_greyctl_free(greyctx);
greyctx = NULL;
SM_TEST(SM_SUCCESS == ret);
error:
if (greyctx != NULL)
sm_greyctl_free(greyctx);
return;
}
int
main(int argc, char *argv[])
{
int c;
bool rm, display;
uint entries, ips;
entries = 1000;
ips = 100;
rm = true;
display = false;
while ((c = getopt(argc, argv, "de:i:k:V")) != -1)
{
switch (c)
{
case 'd':
display = true;
break;
case 'e':
entries = strtoul(optarg, NULL, 0);
break;
case 'i':
ips = strtoul(optarg, NULL, 0);
break;
case 'k':
rm = false;
break;
case 'V':
++Verbose;
break;
default:
return(1);
}
}
if (rm)
{
(void) unlink("grey_grey_m.db");
(void) unlink("grey_grey_s.db");
}
sm_test_begin(argc, argv, "test greylist");
testg(entries, ips, display);
return sm_test_end();
}
syntax highlighted by Code2HTML, v. 0.9.1