/*
* Copyright (c) 2003, 2004, 2006 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"
#if 0
SM_RCSID("@(#)$Id: t-connctl-0.c,v 1.13 2006/05/02 17:13:37 ca Exp $")
#endif /* 0 */
/* For Solaris */
#define _STRPTIME_DONTZERO 1
#include <stdio.h>
#include "sm/types.h"
#include "sm/ctype.h"
#include "sm/string.h"
#include "sm/time.h"
#include "sm/error.h"
#include "sm/net.h"
#include "sm/connctl.h"
#include "sm/test.h"
#define MAXCPM 100
#define MAXLINE 128
static int CollTime = 60;
static int Verbose = 0;
#ifndef CPMHSIZE
# define CPMHSIZE 256
#endif /* CPMHSIZE */
#ifndef MAX_CT_STEPS
# define MAX_CT_STEPS 5
#endif /* MAX_CT_STEPS */
/* Hack... to get a "statistics" version */
#define SM_CONNCTL_PERF 1
#include "../libmta/connctl.c"
static int size = CPMHSIZE;
static int steps = MAX_CT_STEPS;
#if TEST_BHTABLE
#include "sm/bhtable.h"
#define T_BHT_SIZE 4095
#define MAX_OPEN_CONN 100
static ipv4_T open_conns[MAX_OPEN_CONN]; /* used as fifo */
static int oc_first = 0, oc_last = 0;
void
stats(bht_P tn)
{
#if SM_BHT_PERF
char buf[1024];
if (Verbose > 0)
{
bht_stats(tn, buf, sizeof(buf));
fprintf(stderr, "%s\n", buf);
}
#endif /* SM_BHT_PERF */
}
#endif /* TEST_BHTABLE */
/*
** READCONN -- read connection data from file and call connctl
**
** Parameters:
** fp -- file from which to read data
** rdonly -- don't call connctl
** writeit -- write pre-processed data to stdout
** preproc -- input is pre-processed
**
** Returns:
** usual sm_error code
*/
int
readconn(FILE *fp, int rdonly, int writeit, int preproc)
{
sm_ret_T ret;
int r;
char *s, *h;
struct tm tm;
struct in_addr addr;
time_t t, prev;
ulong colls, unused, lc, total, maxcoll;
char line[MAXLINE];
#if TEST_BHTABLE
bht_P tn;
bht_entry_P bi;
#else /* TEST_BHTABLE */
connctx_P cctx;
#endif /* TEST_BHTABLE */
#if TEST_BHTABLE
tn = bht_new(size, size * 10);
SM_TEST(tn != NULL);
if (tn == NULL)
return -1;
#else /* TEST_BHTABLE */
ret = sm_connctl_new(size, steps, &cctx);
SM_TEST(ret == SM_SUCCESS);
#endif /* TEST_BHTABLE */
lc = 0;
prev = 0;
colls = unused = lc = total = maxcoll = 0;
while (fgets(line, sizeof(line), fp) != NULL)
{
++lc;
if (preproc)
t = strtol(line, &s, 10);
else
{
bzero(&tm, sizeof(tm));
tm.tm_year = 103;
tm.tm_wday = 0;
tm.tm_yday = 0;
s = strptime(line, "%b %e %T", &tm);
if (s == NULL)
{
fprintf(stderr, "%ld: can't read date: '%s'\n",
lc, line);
continue;
}
#if HAVE_TIMEGM
t = timegm(&tm);
#else /* HAVE_TIMEGM */
t = mktime(&tm);
#endif /* HAVE_TIMEGM */
}
if (t == -1)
{
fprintf(stderr, "%ld: can't convert time: '%s' (%d)\n",
lc, line, errno);
continue;
}
if (t < prev)
{
fprintf(stderr, "%ld: time went backwards: %ld -> %ld\n",
lc, (long) prev, (long) t);
prev = t;
continue;
}
prev = t;
while (*s != '\0' && *s != '\n' &&
!(isascii(*s) && isdigit(*s)))
++s;
h = s;
while (*h != '\0' && *h != '\n')
++h;
if (*h == '\n')
*h = '\0';
#if HAVE_INET_PTON
r = inet_pton(AF_INET, s, &addr);
#else /* HAVE_INET_PTON */
# if HAVE_INET_ATON
r = inet_aton(s, &addr);
# else /* HAVE_INET_ATON */
/* yeah, right */
SM_TEST(0 == 1);
return -1;
# endif /* HAVE_INET_ATON */
#endif /* HAVE_INET_PTON */
if (r != 1)
{
fprintf(stderr, "%ld: can't read IP addr: '%s', (%d)\n",
lc, s, errno);
continue;
}
if (!rdonly)
{
#if TEST_BHTABLE
open_conns[oc_first++] = (ipv4_T) addr.s_addr;
if (oc_first >= MAX_OPEN_CONN)
oc_first = 0;
if (bht_find(tn, (char *) &addr, sizeof(addr)) == NULL)
{
ret = bht_add(tn, (char *) &addr, sizeof(addr),
"value", &bi);
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
goto done;
SM_TEST(bi != NULL);
}
/*
printf("first=%d, last=%d\n", oc_first, oc_last);
*/
if ((oc_first > oc_last &&
oc_first - oc_last >= MAX_OPEN_CONN - 2) ||
(oc_first < oc_last &&
oc_last - oc_first <= 2))
{
/*
printf("remove first=%d, last=%d, addr=%x\n", oc_first, oc_last, open_conns[oc_last]);
*/
bht_rm(tn, (char *)&(open_conns[oc_last]),
sizeof(open_conns[oc_last]),
NULL, NULL);
++oc_last;
if (oc_last >= MAX_OPEN_CONN)
oc_last = 0;
}
#else /* TEST_BHTABLE */
ret = sm_connctl(cctx, addr, t);
#endif /* TEST_BHTABLE */
}
if (writeit)
printf("%ld %s\n", (long) t, s);
}
#if TEST_BHTABLE
done:
stats(tn);
bht_destroy(tn, NULL, NULL);
#else /* TEST_BHTABLE */
#if SM_CONNCTL_PERF
ret = sm_connctl_stats(cctx, &colls, &maxcoll, &unused, &total);
#endif /* SM_CONNCTL_PERF */
printf("total: %7ld\n", total);
printf("colls: %7ld\n", colls);
printf("maxcolls: %7ld\n", maxcoll);
printf("unused: %7ld\n", unused);
sm_connctl_free(cctx);
#endif /* TEST_BHTABLE */
return 0;
}
int
main(int argc, char *argv[])
{
int i, c, rdonly, writeit, preproc;
FILE *fp;
rdonly = writeit = preproc = 0;
while ((c = getopt(argc, argv, "c:h:prs:Vw")) != -1)
{
switch (c)
{
case 'c':
CollTime = strtol(optarg, NULL, 0);
if (CollTime <= 1)
return 1;
break;
case 'h':
size = strtol(optarg, NULL, 0);
if (size <= 4)
return 1;
break;
case 'p':
++preproc;
break;
case 'r':
++rdonly;
break;
case 's':
steps = strtol(optarg, NULL, 0);
if (steps <= 2 || steps >= size)
return 1;
break;
case 'V':
++Verbose;
break;
case 'w':
++writeit;
break;
default:
return 1;
}
}
sm_test_begin(argc, argv, "test connctl 0");
argc -= optind;
if (argc > 0)
{
for (i = 0; i < argc; i++)
{
if ((fp = fopen(argv[i + optind], "r")) != (FILE *)0)
{
readconn(fp, rdonly, writeit, preproc);
fclose(fp);
}
else
{
fprintf(stderr, "can't read: '%s'\n", argv[i]);
}
}
}
else
readconn(stdin, rdonly, writeit, preproc);
return sm_test_end();
}
syntax highlighted by Code2HTML, v. 0.9.1