--- apps/cflowd/cflowd.cc_dwm Sat Oct 16 05:45:45 1999 +++ apps/cflowd/cflowd.cc Thu Apr 20 22:15:03 2000 @@ -40,12 +40,22 @@ //=========================================================================== extern "C" { +#include /* errno, EINTR */ +#include /* fcntl, open, O_CREAT, O_WRONLY, O_TRUNC, O_RDWR */ +#include /* log */ +#include /* signal, SIGCHLD, SIGTERM, SIGPIPE, SIGTTOU, SIG_IGN */ +#include /* NULL */ +#include /* rename, EOF, fprintf, stderr */ +#include /* exit, strtoul */ +#include /* memset, strcpy, strlen, memcpy */ +#include /* termios */ +#include /* wait, waitpid, WNOHANG */ +#include /* time, time_t, difftime, strftime, localtime, tm, gmtime */ +#include /* unlink, close, fork, write, read, setpgid, getpid */ +static time_t mutt_local_tz (time_t t); #include "aclocal.h" #include -#include #include -#include -#include #ifdef HAVE_SYS_FILIO_H #define BSD_COMP 1 #include @@ -56,6 +66,9 @@ #include "caida_t.h" } +#include +#include + #include "CflowdConfig.hh" #include "CflowdConfigLex.hh" #include "CflowdTableRequest.hh" @@ -73,6 +86,12 @@ static int g_tableSockFd = -1; static CflowdPacketQueue g_packetQueue; bool g_cflowdDebug = false; +static time_t g_logtimeout = (time_t) -1; +static int g_logfd = -1; +static int g_skip_output_if = -1; +static int g_retain_multicast = 0; // boolean +static unsigned long g_multimask = inet_addr("240.0.0.0"); +static unsigned long g_multinet = inet_addr("224.0.0.0"); Signal g_sigChld(SIGCHLD); Signal g_sigTerm(SIGTERM); @@ -562,6 +581,8 @@ int numPackets, numFlows; CflowdRawFlow flow; CflowdCiscoMap::iterator ciscoMapIter; + time_t now; + static time_t then; uint16_t exportVersion; ipv4addr_t ciscoAddr; @@ -661,10 +682,64 @@ numFlows = flowArrNum; + + if ((time_t)-1 != g_logtimeout) { + time(&now); + if (-1 == g_logfd || difftime(now, then) > g_logtimeout) { + string current, previous; + + // remember when we rename(2)d the previous log file: + then = now; + + // generate the current timestamp with trailing "hours east" of UTC: + static char date[sizeof "YYYYMMDD_HH:MI:SS+0000"]; + strftime(date, sizeof date, "%Y%m%d_%H:%M:%S", localtime(&now)); + time_t tz = mutt_local_tz(now); + tz /= 60; // convert to minutes + sprintf(date+sizeof "YYYYMMDD_HH:MI:SS" - sizeof "", "%+03d%02d", + (int)tz/60, (int)abs(tz)%60); + + current = g_cflowdConfig.FlowDirectory(); + current += "/flows.current"; + + previous = g_cflowdConfig.FlowDirectory(); + previous += "/flows."; + previous += date; + + if (-1 != g_logfd) { // rename current log file to previous: + close(g_logfd); + if (-1 == rename(current.c_str(), previous.c_str())) { + syslog(LOG_ERR,"[E] rename(\"%s\", \"%s\"): %m {%s:%d}", + current.c_str(), previous.c_str(), + __FILE__, __LINE__); + } + } + + // open a new current log file: + g_logfd = open(current.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644); + if (-1 == g_logfd) { + syslog(LOG_ERR, + "[E] open(\"%s\", O_CREAT | O_WRONLY | O_TRUNC): %m {%s:%d}", + current.c_str(), __FILE__, __LINE__); + } + } + } + for (flowNum = 0; flowNum < numFlows; flowNum++) { ciscoMapIter = g_cflowdConfig.CiscoMap().find(flows[flowNum].Router()); if (ciscoMapIter != g_cflowdConfig.CiscoMap().end()) { ((*ciscoMapIter).second)->AddFlow(flows[flowNum]); + + // if (the output interface is the one we were asked to skip && + // (we weren't asked to retain multicast flows || + // this isn't a multicast flow)) + if (g_skip_output_if == flows[flowNum].OutputIfIndex() && + (!g_retain_multicast || + (g_multimask & flows[flowNum].DstIpAddr()) != g_multinet)) { + continue; + } + + if (-1 != g_logfd) flows[flowNum].Write(g_logfd); } } @@ -851,11 +926,39 @@ int optChar; char *configFilename = NULL; - while ((optChar = getopt(argc,argv,"D")) != EOF) { + while ((optChar = getopt(argc,argv,"Ds:O:m")) != EOF) { switch (optChar) { case 'D': g_cflowdDebug = true; break; + case 's': + { + char *unconv; + g_logtimeout = strtoul(optarg, &unconv, 10); + if ('\0' != *unconv) { + fprintf(stderr, "usage cflowd [ -s logtimeout_seconds [ -O skip_output_if [-m] ] ]\n"); + exit(2); + } + } + break; + case 'O': + { + char *unconv; + g_skip_output_if = strtoul(optarg, &unconv, 10); + if ('\0' != *unconv) { + fprintf(stderr, "usage cflowd [ -s logtimeout_seconds [ -O skip_output_if [-m] ] ]\n"); + exit(2); + } + } + break; + case 'm': // retain multicast traffic even if we're skipping output_if 0 + // (Multicast flows always show the output_if as 0.) + if (-1 == g_skip_output_if) { + fprintf(stderr, "usage cflowd [ -s logtimeout_seconds [ -O skip_output_if [-m] ] ]\n"); + exit(2); + } + g_retain_multicast = 1; + break; default: break; } @@ -892,3 +995,65 @@ MainLoop(); } + +#if 1 /* { */ + +/* + * Copyright (C) 1996-2000 Michael R. Elkins + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* returns the seconds east of UTC given `g' and its corresponding gmtime() + representation */ +static time_t compute_tz (time_t g, struct tm *utc) +{ + struct tm *lt = localtime (&g); + time_t t; + int yday; + + t = (((lt->tm_hour - utc->tm_hour) * 60) + (lt->tm_min - utc->tm_min)) * 60; + + if ((yday = (lt->tm_yday - utc->tm_yday))) + { + /* This code is optimized to negative timezones (West of Greenwich) */ + if (yday == -1 || /* UTC passed midnight before localtime */ + yday > 1) /* UTC passed new year before localtime */ + t -= 24 * 60 * 60; + else + t += 24 * 60 * 60; + } + + return t; +} + +/* Returns the local timezone in seconds east of UTC for the time t, + * or for the current time if t is zero. + */ +static time_t mutt_local_tz (time_t t) +{ + struct tm *ptm; + struct tm utc; + + if (!t) + t = time (NULL); + ptm = gmtime (&t); + /* need to make a copy because gmtime/localtime return a pointer to + static memory (grr!) */ + memcpy (&utc, ptm, sizeof (utc)); + return (compute_tz (t, &utc)); +} + +#endif /* } */