/* * 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 #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(); }