/* * Copyright (c) 2000-2004 QoSient, LLC * All rights reserved. * * 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, 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. * */ /* * Copyright (c) 1993, 1994 Carnegie Mellon University. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation, and that the name of CMU not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * */ /* * argus_parse - parse argus output. * this module performs all the argus(1) related connection parsing, * selects datum from a set of criteria, and then calls specific * protocol dependant routines, depending on the selected datum. * at the end of processing, argus_parse calls an application * specific finish routine, RaParseComplete(), and when * connected to a remote data source, it supplies a periodic * timeout routine; * * this module defines all things, except: * * (void) usage ((char *) argv[0]); * this routine should print the standard usage message * for the specific application. * * ArgusClientInit (); this is the application specific init * routine, which is called after all parsing * initialization is done, prior to reading the * first monitor(1) datum. * * (void) ArgusClientTimeout (); * this routine is called every second, when * argus_parse is connected to a remote data source. * * process_man ((struct ArgusRecord *) ptr); * this routine should process management control events; * * process_tcp ((struct ArgusRecord *) ptr); * this routine should process tcp events; * * process_udp ((struct ArgusRecord *) ptr); * this routine should process tcp events; * * process_icmp ((struct ArgusRecord *) ptr); * this routine should process tcp events; * * process_ip ((struct ArgusRecord *) ptr); * this routine should process tcp events; * * process_arp ((struct ArgusRecord *) ptr); * this routine should process arp events; * * process_non_ip ((struct ArgusRecord *) ptr); * this routine should process all other events; * * (void) RaParseComplete (0); * this routine will be called after all the * monitor data has been read. * * * written by Carter Bullard * QoSient, LLC * */ #define ArgusParse #include #include #include #if defined(CYGWIN) #include #endif #include #include #include #include #include #include #include #include int ArgusParseResourceFile (char *); unsigned char *ArgusRemoteFilter = NULL; extern void ArgusLog (int, char *, ...); int ArgusParseInit = 0; extern void ArgusClientTimeout (void); #define ARGUS_READINGPREHDR 1 #define ARGUS_READINGHDR 2 #define ARGUS_READINGBLOCK 4 void argus_parse_init (struct ARGUS_INPUT *input) { char errbuf[MAXSTRLEN]; char *device = NULL; struct tm *tm; struct argtimeval tvpbuf, *tvp = &tvpbuf; unsigned int net, mask; int i, fd = 0; if (input != NULL) fd = input->fd; if (initCon) { input->ArgusLocalNet = htonl(initCon->argus_mar.localnet); input->ArgusNetMask = htonl(initCon->argus_mar.netmask); if (tflag && timearg) { tvp->tv_sec = ntohl(initCon->argus_mar.now.tv_sec); tm = localtime((time_t *) &tvp->tv_sec); if (check_time_format (tm, timearg)) ArgusLog (LOG_ERR, "time syntax error %s\n", timearg); } } else { if ((device = argus_lookupdev (errbuf)) != NULL) { argus_lookupnet(device, &net, &mask, errbuf); input->ArgusLocalNet = net; input->ArgusNetMask = mask; } } if ((input->ArgusReadBuffer = (unsigned char *)ArgusCalloc (1, MAXSTRLEN)) == NULL) ArgusLog (LOG_ERR, "ArgusCalloc error %s\n", strerror(errno)); if ((input->ArgusConvBuffer = (u_char *)ArgusCalloc (1, MAXSTRLEN)) == NULL) ArgusLog (LOG_ERR, "ArgusCalloc error %s\n", strerror(errno)); input->ArgusReadPtr = input->ArgusReadBuffer; input->ArgusConvPtr = input->ArgusConvBuffer; if (Cflag) { input->ArgusReadSocketState = ARGUS_READINGPREHDR; /* input->ArgusReadSize = k_maxFlowPacketSize; */ input->ArgusReadSize = 4; } else { if (major_version > 1) input->ArgusReadSocketState = ARGUS_READINGHDR; else { input->ArgusReadSocketState = ARGUS_READINGBLOCK; input->ArgusReadSize = 60; } } input->ArgusReadSocketSize = (input->ArgusReadSize < 0) ? sizeof(struct ArgusRecordHeader) : input->ArgusReadSize; if (!ArgusParseInit++) for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) ArgusRemoteFDs[i] = NULL; #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusParseInit (0x%x) returning\n", input); #endif } int ArgusPortNum = 0; char *getoptStr = "aAbB:cCd:D:E:e:f:F:gGhHiIL:lmM:nN:p:P:qr:RS:s:t:T:uU:vVw:zZ:"; #define RaEnvItems 2 char *RaResourceEnvStr [] = { "HOME", "ARGUSHOME", }; int main (int argc, char **argv) { int i, cc, op, retn = 0, fd = 0, Scmdline = 0, rcmdline = 0; char *cmdbuf = NULL, *infile = NULL; char *envstr = NULL, *homepath = NULL; struct stat statbuf; static char path[MAXPATHNAMELEN]; struct timeval now; struct timezone tz; extern char *optarg; extern int optind, opterr; opterr = 0; for (i = 0, cc = 0; i < argc; i++) cc += strlen(argv[i]); if (cc > 0) { int len = cc + (argc + 1); if ((cmdline = (char *) ArgusCalloc (len, sizeof(char))) != NULL) { for (i = 0, *cmdline = '\0'; i < argc; i++) { strcat (cmdline, argv[i]); strcat (cmdline, " "); } } else ArgusLog (LOG_ERR, "ArgusCalloc(%d, %d) failed %s\n", len, sizeof(char), strerror(errno)); } if (strchr (argv[0], '/')) argv[0] = strrchr(argv[0], '/') + 1; if (gettimeofday(&now, &tz) < 0) error("gettimeofday"); ArgusGlobalTime = now; ArgusNowTime = now; thiszone = tz.tz_minuteswest * -60; if ((RaTmStruct = localtime ((time_t *)&now.tv_sec))) { if (RaTmStruct->tm_isdst) thiszone += 3600; } else { fprintf (stderr, "%s: localtime: error %s \n", *argv, strerror(errno)); exit (1); } ArgusProgramName = argv[0]; snprintf (path, MAXPATHNAMELEN - 1, "/etc/ra.conf"); if (stat (path, &statbuf) == 0) ArgusParseResourceFile (path); if ((homepath = getenv("ARGUSHOME")) != NULL) { snprintf (path, MAXPATHNAMELEN - 1, "%s/ra.conf", homepath); if (stat (path, &statbuf) == 0) { ArgusParseResourceFile (path); } } if ((envstr = getenv("ARGUSPATH")) != NULL) { while ((homepath = strtok(envstr, ":")) != NULL) { snprintf (path, MAXPATHNAMELEN - 1, "%s/.rarc", homepath); if (stat (path, &statbuf) == 0) { ArgusParseResourceFile (path); break; } envstr = NULL; } } else { for (i = 0; i < RaEnvItems; i++) { envstr = RaResourceEnvStr[i]; if ((homepath = getenv(envstr)) != NULL) { sprintf (path, "%s/.rarc", homepath); if (stat (path, &statbuf) == 0) { ArgusParseResourceFile (path); break; } } } } if ((argv[optind]) != NULL) ArgusProgramOptions = strdup(copy_argv (&argv[optind])); while ((op = getopt (argc, argv, getoptStr)) != EOF) { switch (op) { case 'a': ++aflag; break; case 'A': ++Aflag; break; case 'b': ++bflag; break; case 'B': Bflag = atoi(optarg); break; case 'c': ++cflag; break; case 'C': ++Cflag; break; case 'D': Argusdflag = atoi (optarg); break; case 'd': ++dflag; if ((dataarg = optarg) != NULL) { if ((retn = parseUserDataArg (&dataarg, argv, optind)) < 0) { usage (); } else { optind += retn; } } break; case 'e': estr = optarg; if (strncmp(ArgusProgramName, "ragrep", 6)) { if (!(strncasecmp(optarg, "ascii", 5))) eflag = ARGUS_ENCODE_ASCII; else if (!(strncasecmp(optarg, "encode64", 8))) eflag = ARGUS_ENCODE_64; else usage(); } else { ArgusGrepSource++; ArgusGrepDestination++; if ((estr[0] == 's') && (estr[1] == ':')) { ArgusGrepDestination = 0; estr = &estr[2]; } if ((estr[0] == 'd') && (estr[1] == ':')) { ArgusGrepSource = 0; estr = &estr[2]; } } break; case 'E': exceptfile = optarg; break; case 'f': ArgusFlowModelFile = optarg; break; case 'F': if (!(ArgusParseResourceFile (optarg))) ArgusLog (LOG_ERR, "ArgusParseResourceFile(%s) error. %s\n", optarg, strerror(errno)); break; case 'g': ++gflag; Gflag = 0; break; case 'G': ++Gflag; gflag = 0; break; case 'H': ++Hflag; break; case 'i': ++idflag; break; case 'I': ++Iflag; break; case 'L': switch (Lflag = atoi(optarg)) { case 0: Lflag = -1; break; case -1: Lflag = 0; break; } break; case 'l': ++lflag; break; case 'm': ++mflag; break; case 'M': Mflag = optarg; break; case 'n': ++nflag; break; case 'N': Nflag = atoi (optarg); break; case 'p': pflag = atoi (optarg); break; case 'P': ArgusPortNum = atoi (optarg); break; case 'q': ++qflag; break; case 'r': ++rflag; Sflag = 0; if ((!rcmdline++) && (ArgusInputFileList != NULL)) ArgusDeleteFileList(); if (optarg == NULL) optarg = "-"; do { if (!(ArgusAddFileList (optarg))) { fprintf (stderr, "%s: error: file arg %s \n", *argv, optarg); exit (1); } if ((optarg = argv[optind]) != NULL) if (*optarg != '-') optind++; } while (optarg && (*optarg != '-')); break; case 'R': ++Rflag; break; case 's': if (RaSortIndex < ARGUS_MAX_SORT_ALG) RaSortAlgorithmStrings[RaSortIndex++] = optarg; else ArgusLog (LOG_ERR, "usage: number of sort options exceeds %d\n", ARGUS_MAX_SORT_ALG); break; case 'S': ++Sflag; if ((!Scmdline++) && (ArgusRemoteHostList != NULL)) ArgusDeleteHostList(); if (!(ArgusAddHostList (optarg))) { fprintf (stderr, "%s: host %s unknown\n", *argv, optarg); exit (1); } break; case 't': ++tflag; if ((timearg = optarg) != NULL) { if ((retn = parseTimeArg (&timearg, argv, optind, RaTmStruct)) < 0) { usage (); } else { optind += retn; } } break; case 'T': Tflag = atoi(optarg); break; case 'u': uflag++; break; case 'U': ustr = optarg; break; case 'v': vflag++; break; case 'V': Vflag++; break; case 'w': if ((wfile = optarg) == NULL) if (!strcmp (argv[optind], "-")) { wfile = "-"; } break; case 'z': ++zflag; break; case 'Z': Zflag = *optarg; break; case 'h': default: usage (); /* NOTREACHED */ } } if (infile) cmdbuf = read_infile (infile); else { char *str; if ((str = argv[optind]) != NULL) { if (strcmp(str, "-") == 0) optind++; cmdbuf = copy_argv (&argv[optind]); } } if (cmdbuf) { if (RaInputFilter != NULL) ArgusFree(RaInputFilter); RaInputFilter = cmdbuf; } init_addrtoname (fflag, ArgusLocalNet, ArgusNetMask); bzero ((char *) &ArgusFilterCode, sizeof (ArgusFilterCode)); if (!(ArgusFilterCompile (&ArgusFilterCode, RaInputFilter, 1, ArgusNetMask) < 0)) { if (cmdbuf) ArgusRemoteFilter = (unsigned char *) strdup(cmdbuf); else ArgusRemoteFilter = NULL; } if (bflag) { bpf_dump(&ArgusFilterCode, bflag); exit (0); } ArgusClientInit (); if (Sflag) { register struct ARGUS_INPUT *addr; if ((addr = ArgusRemoteHostList) != NULL) { while (addr != NULL) { if ((addr->fd = ArgusGetServerSocket (addr)) >= 0) if ((ArgusReadConnection (addr, NULL)) >= 0) ArgusRemoteFDs[ArgusActiveServers++] = addr; addr = addr->nxt; } } ArgusReadStream(); } else { struct ARGUS_INPUT *addr; if (ArgusInputFileList == NULL) if (!(ArgusAddFileList ("-"))) ArgusLog (LOG_ERR, "ArgusAddFilelist('-') error %s\n", strerror(errno)); if ((addr = ArgusInputFileList) != NULL) { while (addr) { if (strcmp (addr->filename, "-")) { if ((addr->fd = open(addr->filename, O_RDONLY)) >= 0) { if (((ArgusReadConnection (addr, addr->filename)) >= 0)) { ArgusRemoteFDs[0] = addr; ArgusReadStream(); close(addr->fd); } } else { fprintf (stderr, "%s: open '%s': %s\n", ArgusProgramName, addr->filename, strerror(errno)); } } else { addr->fd = 0; if (((ArgusReadConnection (addr, NULL)) >= 0)) { ArgusRemoteFDs[0] = addr; ArgusReadStream(); } } addr = addr->nxt; } } else { struct ARGUS_INPUT addrbuf, *addr = &addrbuf; bzero ((char *) addr, sizeof (*addr)); addr->fd = 0; if (((ArgusReadConnection (addr, NULL)) >= 0)) { ArgusRemoteFDs[0] = addr; ArgusReadStream(); } } } if (fd >= 0) { ArgusShutDown (0); } else retn = 1; #ifdef ARGUSDEBUG ArgusDebug (1, "main () exiting with %d\n", retn); #endif exit (retn); } void ArgusShutDown (int value) { #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusShutDown (%d)\n", value); #endif if (value >= 0) RaParseComplete (value); _exit (value); } unsigned int ArgusTotalCount = 0; unsigned int ArgusTotalBytes = 0; static int firstWrite = 1; int ArgusHandleDatum (struct ArgusRecord *ptr, struct bpf_program *filter) { int retn = 0; if (ptr != NULL) { int len = ntohs(ptr->ahdr.length); struct bpf_insn *fcode = filter->bf_insns; u_char buf[MAXSTRLEN]; totalrecords++; if (len > MAXSTRLEN) ArgusLog (LOG_ERR, "ArgusHandleDatum(0x%x) input record %d size = %d\n", totalrecords, len); bcopy ((char *)ptr, (char *)ArgusOriginal, len); bcopy ((char *)ptr, (char *)&buf, len); switch (ptr->ahdr.type) { case ARGUS_MAR: case (ARGUS_MAR | ARGUS_CISCO_NETFLOW): case ARGUS_INDEX: case ARGUS_EVENT: marrecords++; break; case ARGUS_FAR: case ARGUS_DATASUP: farrecords++; break; } if ((retn = argus_filter (fcode, (unsigned char *) ptr)) != 0) { #ifdef _LITTLE_ENDIAN ArgusNtoH ((struct ArgusRecord *)&buf); #endif ArgusThisFarStatus = ArgusIndexRecord ((struct ArgusRecord *)&buf, ArgusThisFarHdrs); if ((retn = check_time ((struct ArgusRecord *)&buf)) != 0) { struct ArgusRecord *argus = (struct ArgusRecord *)&buf; if (!(ptr->ahdr.type & ARGUS_MAR)) { unsigned int count, bytes; #define ARGUSMAXPACKETSIZE 65536 /* correct for 1.8x byte count bug */ if ((count = argus->argus_far.src.count) > 0) if ((bytes = argus->argus_far.src.bytes) > 0) if ((bytes/count) > ARGUSMAXPACKETSIZE) argus->argus_far.src.bytes = 0; if ((count = argus->argus_far.dst.count) > 0) if ((bytes = argus->argus_far.dst.bytes) > 0) if ((bytes/count) > ARGUSMAXPACKETSIZE) argus->argus_far.dst.bytes = 0; ArgusTotalCount += (argus->argus_far.src.count + argus->argus_far.dst.count); if (Aflag) ArgusTotalBytes += (argus->argus_far.src.appbytes + argus->argus_far.dst.appbytes); else ArgusTotalBytes += (argus->argus_far.src.bytes + argus->argus_far.dst.bytes); } if (wfile) { if (RaWriteOut) { if (!(firstWrite && ((argus->ahdr.type & ARGUS_MAR) && (argus->ahdr.cause & ARGUS_START)))) if (ArgusWriteNewLogfile (wfile, ArgusOriginal)) { fprintf (stderr, "ArgusWriteNewLogfile: error\n"); exit (1); } } else ArgusProcessRecord ((struct ArgusRecord *)&buf); } else ArgusProcessRecord ((struct ArgusRecord *)&buf); } } else { if (exceptfile) { if (ArgusWriteNewLogfile (exceptfile, ArgusOriginal)) { fprintf (stderr, "ArgusWriteNewLogfile: error using file %s\n", exceptfile); exit (1); } } } retn = 0; if (ptr->ahdr.type & ARGUS_MAR) { switch (ptr->ahdr.cause) { case ARGUS_STOP: case ARGUS_SHUTDOWN: case ARGUS_ERROR: { #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusHandleDatum (0x%x, 0x%x) received closing Mar\n", ptr, filter); #endif if (Sflag) retn = 1; break; } } } } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusHandleDatum (0x%x, 0x%x) returning %d\n", ptr, filter, retn); #endif return (retn); } #include struct ArgusRecord *ArgusNetFlowCallRecord (u_char **); struct ArgusRecord *ArgusNetFlowDetailInt (u_char **); struct ArgusRecord *ArgusParseCiscoRecord (u_char **); struct ArgusRecord *ArgusParseCiscoRecordV1 (u_char **); struct ArgusRecord *ArgusParseCiscoRecordV5 (u_char **); struct ArgusRecord *ArgusParseCiscoRecordV6 (u_char **); unsigned char *ArgusNetFlowRecordHeader = NULL; unsigned char ArgusNetFlowArgusRecordBuf[1024]; struct ArgusRecord *ArgusNetFlowArgusRecord = (struct ArgusRecord *) ArgusNetFlowArgusRecordBuf; struct ArgusRecord * ArgusParseCiscoRecordV1 (u_char **ptr) { CiscoFlowEntryV1_t *entryPtrV1 = (CiscoFlowEntryV1_t *) *ptr; CiscoFlowHeaderV1_t *hdrPtrV1 = (CiscoFlowHeaderV1_t *) ArgusNetFlowRecordHeader; struct ArgusRecord *argus = ArgusNetFlowArgusRecord; struct ArgusMacStruct mac; *ptr += sizeof(CiscoFlowEntryV1_t); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV1) { long time; time = ntohl(entryPtrV1->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV1->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV1->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV1->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV1->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV1->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV1->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV1->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV1->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV1->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV1->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV1->dstaddr); argus->argus_far.flow.ip_flow.ip_p = entryPtrV1->prot; argus->argus_far.attr_ip.stos = entryPtrV1->tos; argus->argus_far.src.count = ntohl(entryPtrV1->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV1->bytes); argus->argus_far.src.appbytes = 0; switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { struct ArgusTCPObject tcpbuf, *tcp = &tcpbuf; bzero ((char *) tcp, sizeof(*tcp)); tcp->type = ARGUS_TCP_DSR; tcp->length = sizeof(struct ArgusTCPObject); tcp->src.flags = entryPtrV1->flags; if (tcp->src.flags & TH_RST) { if (argus->argus_far.src.count == 1) { if (tcp->src.flags == (TH_RST | TH_ACK)) tcp->state |= ARGUS_DST_RESET; else tcp->state |= ARGUS_SRC_RESET; } else tcp->state |= ARGUS_RESET; } if (tcp->src.flags & TH_FIN) tcp->state |= ARGUS_FIN; if ((tcp->src.flags & TH_ACK) || (tcp->src.flags & TH_PUSH) || (tcp->src.flags & TH_URG)) tcp->state |= ARGUS_CON_ESTABLISHED; switch (tcp->src.flags & (TH_SYN|TH_ACK|TH_FIN|TH_PUSH|TH_URG)) { case (TH_SYN): tcp->state |= ARGUS_SAW_SYN; break; case (TH_SYN|TH_ACK): if (argus->argus_far.src.count == 1) tcp->state |= ARGUS_SAW_SYN_SENT; break; } bcopy ((char *)tcp, &((char *)argus)[argus->ahdr.length], sizeof(*tcp)); argus->ahdr.length += sizeof(*tcp); } /* fall through to UDP switch to get the ports */ case IPPROTO_UDP: argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV1->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV1->dstport); break; case IPPROTO_ICMP: { argus->argus_far.flow.icmp_flow.type = ((char *)&entryPtrV1->dstport)[0]; argus->argus_far.flow.icmp_flow.code = ((char *)&entryPtrV1->dstport)[1]; } break; } bzero ((char *)&mac, sizeof (mac)); mac.type = ARGUS_MAC_DSR; mac.length = sizeof(mac); mac.status = 0; entryPtrV1->input = ntohs(entryPtrV1->input); entryPtrV1->output = ntohs(entryPtrV1->output); bcopy((char *)&entryPtrV1->input, (char *)&mac.phys_union.ether.ethersrc[4], 2); bcopy((char *)&entryPtrV1->output,(char *)&mac.phys_union.ether.etherdst[4], 2); bcopy ((char *)&mac, &((char *)argus)[argus->ahdr.length], sizeof(mac)); argus->ahdr.length += sizeof(mac); #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusParseCiscoRecordV1 (0x%x) returning 0x%x\n", *ptr, argus); #endif return(argus); } struct ArgusRecord * ArgusParseCiscoRecordV5 (u_char **ptr) { CiscoFlowEntryV5_t *entryPtrV5 = ((CiscoFlowEntryV5_t *) *ptr); CiscoFlowHeaderV5_t *hdrPtrV5 = (CiscoFlowHeaderV5_t *) ArgusNetFlowRecordHeader; struct ArgusRecord *argus = ArgusNetFlowArgusRecord; struct ArgusMacStruct mac; *ptr += sizeof(CiscoFlowEntryV5_t); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV5) { long time; time = ntohl(entryPtrV5->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV5->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV5->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV5->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV5->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV5->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV5->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV5->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV5->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV5->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV5->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV5->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV5->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV5->dstport); argus->argus_far.flow.ip_flow.ip_p = entryPtrV5->prot; argus->argus_far.attr_ip.stos = entryPtrV5->tos; argus->argus_far.src.count = ntohl(entryPtrV5->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV5->bytes); argus->argus_far.src.appbytes = 0; switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { struct ArgusTCPObject tcpbuf, *tcp = &tcpbuf; bzero ((char *) tcp, sizeof(*tcp)); tcp->type = ARGUS_TCP_DSR; tcp->length = sizeof(struct ArgusTCPObject); tcp->src.flags = entryPtrV5->tcp_flags; if (tcp->src.flags & TH_RST) tcp->status |= ARGUS_RESET; if (tcp->src.flags & TH_FIN) tcp->status |= ARGUS_FIN; if ((tcp->src.flags & TH_ACK) || (tcp->src.flags & TH_PUSH) || (tcp->src.flags & TH_URG)) tcp->status |= ARGUS_CON_ESTABLISHED; switch (tcp->src.flags & (TH_SYN|TH_ACK|TH_FIN|TH_PUSH|TH_URG)) { case (TH_SYN): tcp->status |= ARGUS_SAW_SYN; break; } bcopy ((char *)tcp, &((char *)argus)[argus->ahdr.length], sizeof(*tcp)); argus->ahdr.length += sizeof(*tcp); } break; } bzero ((char *)&mac, sizeof (mac)); mac.type = ARGUS_MAC_DSR; mac.length = sizeof(mac); mac.status = 0; entryPtrV5->input = ntohs(entryPtrV5->input); entryPtrV5->output = ntohs(entryPtrV5->output); bcopy((char *)&entryPtrV5->input, (char *)&mac.phys_union.ether.ethersrc[4], 2); bcopy((char *)&entryPtrV5->output,(char *)&mac.phys_union.ether.etherdst[4], 2); bcopy ((char *)&mac, &((char *)argus)[argus->ahdr.length], sizeof(mac)); argus->ahdr.length += sizeof(mac); #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusParseCiscoRecordV5 (0x%x) returning 0x%x\n", *ptr, argus); #endif return (argus); } struct ArgusRecord * ArgusParseCiscoRecordV6 (u_char **ptr) { CiscoFlowEntryV6_t *entryPtrV6 = (CiscoFlowEntryV6_t *) *ptr; CiscoFlowHeaderV6_t *hdrPtrV6 = (CiscoFlowHeaderV6_t *) ArgusNetFlowRecordHeader; struct ArgusRecord *argus = ArgusNetFlowArgusRecord; struct ArgusMacStruct mac; *ptr += sizeof(CiscoFlowEntryV6_t); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV6) { long time; time = ntohl(entryPtrV6->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV6->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV6->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV6->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV6->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV6->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV6->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV6->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV6->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV6->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV6->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV6->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV6->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV6->dstport); argus->argus_far.flow.ip_flow.ip_p = entryPtrV6->prot; argus->argus_far.attr_ip.stos = entryPtrV6->tos; argus->argus_far.src.count = ntohl(entryPtrV6->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV6->bytes); argus->argus_far.src.appbytes = 0; switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: { struct ArgusTCPObject tcpbuf, *tcp = &tcpbuf; bzero ((char *) tcp, sizeof(*tcp)); tcp->type = ARGUS_TCP_DSR; tcp->length = sizeof(struct ArgusTCPObject); tcp->src.flags = entryPtrV6->tcp_flags; if (tcp->src.flags & TH_RST) tcp->status |= ARGUS_RESET; if (tcp->src.flags & TH_FIN) tcp->status |= ARGUS_FIN; if ((tcp->src.flags & TH_ACK) || (tcp->src.flags & TH_PUSH) || (tcp->src.flags & TH_URG)) tcp->status |= ARGUS_CON_ESTABLISHED; switch (tcp->src.flags & (TH_SYN|TH_ACK|TH_FIN|TH_PUSH|TH_URG)) { case (TH_SYN): tcp->status |= ARGUS_SAW_SYN; break; } bcopy ((char *)tcp, &((char *)argus)[argus->ahdr.length], sizeof(*tcp)); argus->ahdr.length += sizeof(*tcp); } break; } bzero ((char *)&mac, sizeof (mac)); mac.type = ARGUS_MAC_DSR; mac.length = sizeof(mac); mac.status = 0; entryPtrV6->input = ntohs(entryPtrV6->input); entryPtrV6->output = ntohs(entryPtrV6->output); bcopy((char *)&entryPtrV6->input, (char *)&mac.phys_union.ether.ethersrc[4], 2); bcopy((char *)&entryPtrV6->output,(char *)&mac.phys_union.ether.etherdst[4], 2); bcopy ((char *)&mac, &((char *)argus)[argus->ahdr.length], sizeof(mac)); argus->ahdr.length += sizeof(mac); #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusParseCiscoRecord (0x%x) returning 0x%x\n", *ptr, argus); #endif return(argus); } struct ArgusRecord * ArgusParseCiscoRecord (u_char **ptr) { struct ArgusRecord *argus = ArgusNetFlowArgusRecord; unsigned short *sptr = (unsigned short *) *ptr; #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusParseCiscoRecord (0x%x) version %h\n", *ptr, *sptr); #endif switch (*sptr) { case Version1: { CiscoFlowHeaderV1_t *hdrPtrV1 = (CiscoFlowHeaderV1_t *) *ptr; CiscoFlowEntryV1_t *entryPtrV1 = (CiscoFlowEntryV1_t *) (hdrPtrV1 + 1); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV1) { long time; time = ntohl(entryPtrV1->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV1->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV1->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV1->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV1->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV1->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV1->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV1->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV1->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV1->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV1->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV1->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV1->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV1->dstport); argus->argus_far.flow.ip_flow.ip_p = entryPtrV1->prot; argus->argus_far.attr_ip.stos = entryPtrV1->tos; argus->argus_far.src.count = ntohl(entryPtrV1->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV1->bytes); #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif break; } case Version5: { CiscoFlowHeaderV5_t *hdrPtrV5 = (CiscoFlowHeaderV5_t *) ptr; CiscoFlowEntryV5_t *entryPtrV5 = (CiscoFlowEntryV5_t *) (hdrPtrV5 + 1); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV5) { long time; time = ntohl(entryPtrV5->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV5->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV5->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV5->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV5->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV5->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV5->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV5->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV5->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV5->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV5->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV5->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV5->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV5->dstport); argus->argus_far.flow.ip_flow.ip_p = entryPtrV5->prot; argus->argus_far.attr_ip.stos = entryPtrV5->tos; argus->argus_far.src.count = ntohl(entryPtrV5->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV5->bytes); argus->argus_far.src.appbytes = 0; #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif break; } case Version6: { CiscoFlowHeaderV6_t *hdrPtrV6 = (CiscoFlowHeaderV6_t *) ptr; CiscoFlowEntryV6_t *entryPtrV6 = (CiscoFlowEntryV6_t *) (hdrPtrV6 + 1); bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); if (hdrPtrV6) { long time; time = ntohl(entryPtrV6->first); argus->argus_far.time.start.tv_sec = (time - (long)hdrPtrV6->sysUptime)/1000; argus->argus_far.time.start.tv_sec += hdrPtrV6->unix_secs; argus->argus_far.time.start.tv_usec = ((time - (long)hdrPtrV6->sysUptime)%1000) * 1000; argus->argus_far.time.start.tv_usec += hdrPtrV6->unix_nsecs/1000; if (argus->argus_far.time.start.tv_usec >= 1000000) { argus->argus_far.time.start.tv_sec++; argus->argus_far.time.start.tv_usec -= 1000000; } if (argus->argus_far.time.start.tv_usec < 0) { argus->argus_far.time.start.tv_sec--; argus->argus_far.time.start.tv_usec += 1000000; } time = ntohl(entryPtrV6->last); argus->argus_far.time.last.tv_sec = (time - (long)hdrPtrV6->sysUptime)/1000; argus->argus_far.time.last.tv_sec += hdrPtrV6->unix_secs; argus->argus_far.time.last.tv_usec = ((time - (long)hdrPtrV6->sysUptime)%1000) * 1000; argus->argus_far.time.last.tv_usec += hdrPtrV6->unix_nsecs/1000; if (argus->argus_far.time.last.tv_usec >= 1000000) { argus->argus_far.time.last.tv_sec++; argus->argus_far.time.last.tv_usec -= 1000000; } if (argus->argus_far.time.last.tv_usec < 0) { argus->argus_far.time.last.tv_sec--; argus->argus_far.time.last.tv_usec += 1000000; } argus->argus_far.time.start.tv_usec = (argus->argus_far.time.start.tv_usec / 1000) * 1000; argus->argus_far.time.last.tv_usec = (argus->argus_far.time.last.tv_usec / 1000) * 1000; } argus->argus_far.flow.ip_flow.ip_src = ntohl(entryPtrV6->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(entryPtrV6->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(entryPtrV6->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(entryPtrV6->dstport); argus->argus_far.flow.ip_flow.ip_p = entryPtrV6->prot; argus->argus_far.attr_ip.stos = entryPtrV6->tos; argus->argus_far.src.count = ntohl(entryPtrV6->pkts); argus->argus_far.src.bytes = ntohl(entryPtrV6->bytes); argus->argus_far.src.appbytes = 0; #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif break; } case Version8: { break; } } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusParseCiscoRecord (0x%x) returning 0x%x\n", *ptr, argus); #endif return (argus); } struct ArgusRecord * ArgusNetFlowCallRecord (u_char **ptr) { struct ArgusRecord *argus = ArgusNetFlowArgusRecord; BinaryRecord_CallRecord_V1 *call = (BinaryRecord_CallRecord_V1 *) *ptr; if (*ptr) { bzero ((char *) argus, sizeof (*argus)); argus->ahdr.type = ARGUS_FAR | ARGUS_CISCO_NETFLOW; argus->ahdr.cause = ARGUS_STATUS; argus->ahdr.length = sizeof(argus->ahdr) + sizeof(argus->argus_far); argus->ahdr.status |= ETHERTYPE_IP; argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); argus->argus_far.time.start.tv_sec = ntohl(call->starttime); argus->argus_far.time.last.tv_sec = ntohl(call->endtime); argus->argus_far.time.last.tv_usec = ntohl(call->activetime) % 1000000; argus->argus_far.time.last.tv_sec += ntohl(call->activetime) / 1000000; argus->argus_far.flow.ip_flow.ip_src = ntohl(call->srcaddr); argus->argus_far.flow.ip_flow.ip_dst = ntohl(call->dstaddr); argus->argus_far.flow.ip_flow.sport = ntohs(call->srcport); argus->argus_far.flow.ip_flow.dport = ntohs(call->dstport); argus->argus_far.flow.ip_flow.ip_p = call->prot; argus->argus_far.attr_ip.stos = call->tos; argus->argus_far.src.count = ntohl(call->pkts); argus->argus_far.src.bytes = ntohl(call->octets); argus->argus_far.src.appbytes = 0; #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusNetFlowCallRecord (0x%x) returns 0x%x\n", *ptr, argus); #endif return (argus); } struct ArgusRecord * ArgusNetFlowDetailInt (u_char **ptr) { struct ArgusRecord *argus = ArgusNetFlowArgusRecord; BinaryRecord_DetailInterface_V1 *dint = (BinaryRecord_DetailInterface_V1 *) *ptr; if (*ptr) { dint = NULL; bzero ((char *) argus, sizeof (*argus)); } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusNetFlowDetailInt (0x%x) returns 0x%x\n", *ptr, argus); #endif return (argus); } ArgusNetFlowHandler ArgusLookUpNetFlow(struct ARGUS_INPUT *, int); struct ArgusNetFlowParsers { int type, size; ArgusNetFlowHandler proc; }; struct ArgusNetFlowParsers ArgusNetFlowParsers [] = { { SourceNode, 0, NULL }, { DestNode, 0, NULL }, { HostMatrix, 0, NULL }, { SourcePort, 0, NULL }, { DestPort, 0, NULL }, { Protocol, 0, NULL }, { DetailDestNode, 0, NULL }, { DetailHostMatrix, 0, NULL }, { DetailInterface, sizeof(BinaryRecord_DetailInterface_V1), ArgusNetFlowDetailInt }, { CallRecord, sizeof(BinaryRecord_CallRecord_V1), ArgusNetFlowCallRecord }, { ASMatrix, 0, NULL }, { NetMatrix, 0, NULL }, { DetailSourceNode, 0, NULL }, { DetailASMatrix, 0, NULL }, { ASHostMatrix, 0, NULL }, { HostMatrixInterface, 0, NULL }, { DetailCallRecord, 0, NULL }, { RouterAS, 0, NULL }, { RouterProtoPort, 0, NULL }, { RouterSrcPrefix, 0, NULL }, { RouterDstPrefix, 0, NULL }, { RouterPrefix, 0, NULL }, { -1, 0, NULL }, }; ArgusNetFlowHandler ArgusCiscoNetFlowParse = NULL; int ArgusWriteConnection (struct ARGUS_INPUT *, unsigned char *, int); ArgusNetFlowHandler ArgusLookUpNetFlow(struct ARGUS_INPUT *input, int type) { ArgusNetFlowHandler retn = NULL; struct ArgusNetFlowParsers *p = ArgusNetFlowParsers; do { if (type == p->type) { retn = p->proc; input->ArgusReadSize = p->size; break; } p++; } while (p->type != -1); #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusLookUpNetFlow (0x%x, %d) returning 0x%x\n", input, type, retn); #endif return (retn); } extern char *ArgusVersionStr; int ArgusReadConnection (struct ARGUS_INPUT *input, char *filename) { struct ArgusCanonicalRecord canonbuf, *canon = &canonbuf; struct ArgusRecord argus; u_char *ptr = (u_char *)&argus; unsigned char buf[MAXSTRLEN]; int cnt, fd = -1; if (input != NULL) fd = input->fd; else fd = 0; if (fd >= 0) { switch (input->status & (ARGUS_DATA_SOURCE | ARGUS_CISCO_DATA_SOURCE)) { case ARGUS_DATA_SOURCE: bzero ((char *) &argus, sizeof(argus)); if ((cnt = read (fd, &argus, sizeof(argus.ahdr))) == sizeof(argus.ahdr)) { #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadConnection() read %d bytes\n", cnt); #endif if (filename) { if (((ptr[0] == 0x1F) && ((ptr[1] == 0x8B) || (ptr[1] == 0x9D))) || ((ptr[0] == 'B') && (ptr[1] == 'Z') && (ptr[2] == 'h'))) { char cmd[256]; bzero(cmd, 256); close(fd); if (ptr[0] == 'B') strcpy(cmd, "bzip2 -dc "); else if (ptr[1] == 0x8B) strcpy(cmd, "gzip -dc "); else strcpy(cmd, "zcat "); strcat(cmd, filename); if ((input->pipe = popen(cmd, "r")) == NULL) { ArgusLog (LOG_ERR, "ArgusReadConnection: popen(%s) failed. %s\n", cmd, strerror(errno)); close (fd); return (-1); } else { fd = fileno(input->pipe); if ((cnt = read (fd, &argus, sizeof(argus.ahdr))) != sizeof(argus.ahdr)) { ArgusLog (LOG_ERR, "ArgusReadConnection: read from '%s' failed. %s\n", cmd, strerror(errno)); pclose(input->pipe); input->pipe = NULL; close (fd); return (-1); } } } } if (argus.ahdr.type & ARGUS_MAR) { unsigned short length = ntohs(argus.ahdr.length); unsigned int argusid = ntohl(argus.ahdr.argusid); unsigned int sequence = ntohl(argus.ahdr.seqNumber); unsigned int status = ntohl(argus.ahdr.status); if (argus.ahdr.cause & ARGUS_ERROR) { #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadConnection() ARGUS_ERROR Mar.\n"); #endif if (status & ARGUS_MAXLISTENEXCD) { fprintf (stderr, "%s: remote exceed listen error.\n", ArgusProgramName); close (fd); return (-1); } } if (argus.ahdr.cause == ARGUS_START) { #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadConnection() ARGUS_START Mar.\n"); #endif input->status |= ARGUS_DATA_SOURCE; if ((argusid == ARGUS_COOKIE) && (sequence == 0)) { int size = length - sizeof(argus.ahdr); if ((cnt = read (fd, &argus.argus_mar, size)) != size) { #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadConnection() read failed for ARGUS_START Mar %s.\n", strerror(errno)); #endif close (fd); return (-1); } bcopy ((char *) &argus, (char *)&input->ArgusInitCon, sizeof (argus)); bcopy ((char *) &argus, (char *) ArgusOriginal, length); ArgusInput = input; ArgusHandleDatum ((struct ArgusRecord *)&argus, &ArgusFilterCode); #ifdef _LITTLE_ENDIAN ArgusNtoH(&argus); #endif bcopy ((char *) &argus, (char *)&input->ArgusManStart, sizeof (argus)); input->major_version = MAJOR_VERSION_2; input->minor_version = MINOR_VERSION_0; input->ArgusReadSize = argus.argus_mar.record_len; argus_parse_init (input); if (Sflag && (input->major_version >= MAJOR_VERSION_2)) { if (ntohl(argus.ahdr.status) & ARGUS_SASL_AUTHENTICATE) { if (!(ArgusAuthenticate(input))) { fprintf (stderr, "%s: incorrect password\n", ArgusProgramName); close(fd); return (-1); } } if ((ArgusRemoteFilter != NULL) && (filename == NULL) && (fd != 0)) { int len; snprintf ((char *) buf, MAXSTRLEN-1, "FILTER: man or %s", (char *) ArgusRemoteFilter); len = strlen((char *) buf); if ((cnt = write (fd, buf, len)) != len) { fprintf (stderr, "%s: write remote filter error %s.\n", ArgusProgramName, strerror(errno)); close(fd); return (-1); } } } } else { fprintf (stderr, "%s: not Argus-2.0 data stream.\n", ArgusProgramName); close(fd); fd = -1; } } else { struct WriteStruct *ws = NULL; char *ptr; int size; bcopy ((char *)&argus, buf, sizeof(argus.ahdr)); size = sizeof(*ws) - sizeof(argus.ahdr); if ((cnt = read (fd, &buf[sizeof(argus.ahdr)], size)) != size) { fprintf (stderr, "%s: reading %d bytes, got %d bytes. %s", ArgusProgramName, size, cnt, strerror(errno)); close (fd); return (-1); } else ws = (struct WriteStruct *) buf; if ((ptr = strstr (ws->ws_init.initString, ArgusVersionStr)) != NULL) { ArgusConvertInitialWriteStruct (ws, &argus); input->major_version = argus.argus_mar.major_version; input->minor_version = argus.argus_mar.minor_version; input->ArgusReadSize = sizeof(*ws); if (initCon == NULL) { if ((initCon = (struct ArgusRecord *) calloc (1, sizeof (argus))) != NULL) bcopy ((char *) &argus, (char *) initCon, sizeof (argus)); } bcopy ((char *) &argus, (char *)&input->ArgusInitCon, sizeof (argus)); bcopy ((char *)&argus, (char *) ArgusOriginal, sizeof(argus)); ArgusInput = input; ArgusHandleDatum ((struct ArgusRecord *)&argus, &ArgusFilterCode); #ifdef _LITTLE_ENDIAN ArgusNtoH(&argus); #endif argus_parse_init (input); input->status |= ARGUS_DATA_SOURCE; } else { fprintf (stderr, "%s: not Argus-2.0 data stream.\n", ArgusProgramName); close(fd); fd = -1; } } } else { char *ptr = (char *)&argus; #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusReadConnection() testing for CISCO records\n"); #endif if (!(strncmp(&ptr[3], "SOURCE", 6))) { BinaryHeaderF2 *ArgusNetFlow = (BinaryHeaderF2 *) buf; int size; bcopy ((char *)&argus, buf, sizeof(argus.ahdr)); size = sizeof(*ArgusNetFlow) - sizeof(argus.ahdr); if ((cnt = read (fd, &buf[sizeof(argus.ahdr)], size)) != size) { fprintf (stderr, "%s: reading %d bytes, got %d bytes. %s", ArgusProgramName, size, cnt, strerror(errno)); close (fd); return (-1); } else { #ifdef _LITTLE_ENDIAN ArgusNetFlow->starttime = ntohl(ArgusNetFlow->starttime); ArgusNetFlow->endtime = ntohl(ArgusNetFlow->endtime); ArgusNetFlow->flows = ntohl(ArgusNetFlow->flows); ArgusNetFlow->missed = ntohl(ArgusNetFlow->missed); ArgusNetFlow->records = ntohl(ArgusNetFlow->records); #endif bzero ((char *)&argus, sizeof(argus)); argus.ahdr.type = ARGUS_MAR | ARGUS_CISCO_NETFLOW; argus.ahdr.length = sizeof (argus); argus.ahdr.cause = ARGUS_START; argus.ahdr.argusid = ARGUS_COOKIE; argus.argus_mar.startime.tv_sec = ArgusNetFlow->starttime; argus.argus_mar.now.tv_sec = ArgusNetFlow->starttime; argus.argus_mar.major_version = major_version; argus.argus_mar.minor_version = minor_version; argus.argus_mar.flows = ArgusNetFlow->flows; argus.argus_mar.pktsDrop = ArgusNetFlow->missed; argus.argus_mar.record_len = -1; input->major_version = argus.argus_mar.major_version; input->minor_version = argus.argus_mar.minor_version; if ((input->ArgusCiscoNetFlowParse = ArgusLookUpNetFlow(input, ArgusNetFlow->aggregation)) != NULL) { #ifdef _LITTLE_ENDIAN ArgusHtoN(&argus); #endif if (initCon == NULL) { if ((initCon = (struct ArgusRecord *) calloc (1, sizeof (argus))) != NULL) bcopy ((char *) &argus, (char *) initCon, sizeof (argus)); } bcopy ((char *) &argus, (char *)&input->ArgusInitCon, sizeof (argus)); bcopy ((char *) &argus, (char *) ArgusOriginal, sizeof(argus)); ArgusInput = input; ArgusGenerateCanonicalRecord (&argus, canon); #ifdef _LITTLE_ENDIAN ArgusNtoH(&argus); #endif argus_parse_init (input); if (check_time (&argus)) { if (!(wfile) || !(wfile || RaWriteOut)) ArgusProcessRecord(&argus); } input->status |= ARGUS_CISCO_DATA_SOURCE; } else { fprintf (stderr, "%s: not supported Cisco data stream.\n", ArgusProgramName); close(fd); fd = -1; } } } else { fprintf (stderr, "%s: not Argus-2.0 data stream.\n", ArgusProgramName); close(fd); fd = -1; } } } else { fprintf (stderr, "%s: no data in data stream.\n", ArgusProgramName); close(fd); fd = -1; } break; case ARGUS_CISCO_DATA_SOURCE: #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusReadConnection(0x%x) reading from Cisco Router.\n", input); #endif bzero((char *)&argus, sizeof(argus)); argus.ahdr.type = ARGUS_MAR | ARGUS_CISCO_NETFLOW; argus.ahdr.length = sizeof (argus); argus.ahdr.cause = ARGUS_START; argus.ahdr.argusid = ARGUS_COOKIE; argus.argus_mar.startime.tv_sec = ArgusGlobalTime.tv_sec; argus.argus_mar.now.tv_sec = ArgusGlobalTime.tv_sec; argus.argus_mar.major_version = major_version; argus.argus_mar.minor_version = minor_version; argus.argus_mar.record_len = -1; input->major_version = argus.argus_mar.major_version; input->minor_version = argus.argus_mar.minor_version; #ifdef _LITTLE_ENDIAN ArgusHtoN(&argus); #endif if (initCon == NULL) { if ((initCon = (struct ArgusRecord *) calloc (1, sizeof (argus))) != NULL) bcopy ((char *) &argus, (char *) initCon, sizeof (argus)); } bcopy ((char *) &argus, (char *)&input->ArgusInitCon, sizeof (argus)); bcopy ((char *) &argus, (char *) ArgusOriginal, sizeof(argus)); ArgusInput = input; argus_parse_init (input); break; } } #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadConnection() returning %d\n", fd); #endif return (fd); } void ArgusCloseInput(struct ARGUS_INPUT *); int ArgusReadStreamSocket (struct ARGUS_INPUT *); int ArgusReadCiscoStreamSocket (struct ARGUS_INPUT *); int ArgusReadCiscoDatagramSocket (struct ARGUS_INPUT *); void ArgusCloseInput(struct ARGUS_INPUT *input) { if (input->pipe) { pclose(input->pipe); input->pipe = NULL; } if (input->in != NULL) fclose(input->in); if (input->out != NULL) fclose(input->out); if (input->ArgusReadBuffer != NULL) ArgusFree(input->ArgusReadBuffer); if (input->ArgusConvBuffer != NULL) ArgusFree(input->ArgusConvBuffer); close (input->fd); #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusCloseInput(0x%x) done\n", input); #endif } #ifdef ARGUS_SASL #include int ArgusReadSaslStreamSocket (struct ARGUS_INPUT *); int ArgusReadSaslStreamSocket (struct ARGUS_INPUT *input) { int retn = 0, fd = input->fd, cnt; unsigned int value = 0, *pvalue = &value; struct ArgusRecord *argus = NULL; char *output = NULL, *end = NULL, *ptr = NULL; unsigned int outputlen = 0; if ((retn = sasl_getprop(input->sasl_conn, SASL_MAXOUTBUF, (void **) &pvalue)) != SASL_OK) ArgusLog (LOG_ERR, "ArgusReadSaslStreamSocket: sasl_getprop %s\n", strerror(errno)); if (value == 0) value = MAXSTRLEN; if ((cnt = read (fd, input->ArgusSaslBuffer + input->ArgusSaslBufCnt, MAXSTRLEN)) > 0) { input->ArgusSaslBufCnt = cnt; ptr = input->ArgusSaslBuffer; do { cnt = (input->ArgusSaslBufCnt > value) ? value : input->ArgusSaslBufCnt; if (sasl_decode (input->sasl_conn, ptr, cnt, &output, &outputlen) == SASL_OK) { #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadSaslStreamSocket (0x%x) sasl_decoded %d bytes\n", input, outputlen); #endif ptr += cnt; if (outputlen) { argus = (struct ArgusRecord *) output; end = output + outputlen; while ((char *)argus < end) { input->ArgusReadSocketCnt = ntohs(argus->ahdr.length); bcopy (argus, input->ArgusReadBuffer, input->ArgusReadSocketCnt); if (ArgusHandleDatum (argus, &ArgusFilterCode) == 1) { if (!input->filename) write (fd, "DONE: ", strlen("DONE: ")); retn = 1; break; } else (char *)argus += input->ArgusReadSocketCnt; } free (output); input->ArgusSaslBufCnt -= cnt; } else { input->ArgusSaslBufCnt = 0; break; } } else { ArgusLog (LOG_ERR, "ArgusReadSaslStreamSocket: sasl_decode () failed"); break; } } while (input->ArgusSaslBufCnt > 0); } else { retn = 1; if ((cnt < 0) && ((errno == EAGAIN) || (errno == EINTR))) { retn = 0; } } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadSaslStreamSocket (0x%x) returning %d\n", input, retn); #endif return (retn); } #endif /* ARGUS_SASL */ int ArgusReadStreamSocket (struct ARGUS_INPUT *input) { int retn = 0, fd = input->fd, cnt = 0; unsigned short length; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadStreamSocket (0x%x) starting\n", input); #endif if ((cnt = read (fd, input->ArgusReadPtr + input->ArgusReadSocketCnt, (input->ArgusReadSocketSize - input->ArgusReadSocketCnt))) > 0) { input->ArgusReadSocketCnt += cnt; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadStreamSocket (0x%x) read %d bytes\n", input, cnt); #endif if (input->ArgusReadSocketCnt == input->ArgusReadSocketSize) { if (input->ArgusReadSocketState == ARGUS_READINGHDR) { input->ArgusReadSocketState = ARGUS_READINGBLOCK; bcopy ((char *)&((struct ArgusRecordHeader *)input->ArgusReadPtr)->length, (char *)&length, sizeof(length)); input->ArgusReadSocketSize = ntohs(length) - sizeof(struct ArgusRecordHeader); input->ArgusReadPtr = &input->ArgusReadBuffer[input->ArgusReadSocketCnt]; input->ArgusReadSocketCnt = 0; } else { if (input->major_version < 2) { ArgusConvertWriteStruct ((struct WriteStruct *)input->ArgusReadBuffer, (struct ArgusRecord *)input->ArgusConvBuffer); bcopy (input->ArgusConvBuffer, input->ArgusReadBuffer, MAXSTRLEN); } if (ArgusHandleDatum ((struct ArgusRecord *)input->ArgusReadBuffer, &ArgusFilterCode) == 1) { if (!input->filename) { write (fd, "DONE: ", strlen("DONE: ")); retn = 1; } } if (input->major_version >= 2) { input->ArgusReadSocketState = ARGUS_READINGHDR; input->ArgusReadSocketSize = sizeof(struct ArgusRecordHeader); } input->ArgusReadPtr = input->ArgusReadBuffer; bzero (input->ArgusReadBuffer, MAXSTRLEN); input->ArgusReadSocketCnt = 0; } } } else { #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadStreamSocket (0x%x) read returned %d\n", input, cnt); #endif retn = 1; if ((cnt < 0) && ((errno == EAGAIN) || (errno == EINTR))) { retn = 0; } } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadStreamSocket (0x%x) returning %d\n", input, retn); #endif return (retn); } int ArgusReadCiscoStreamSocket (struct ARGUS_INPUT *input) { int cnt = 0, retn = 0; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadCiscoStreamSocket (0x%x) starting\n", input); #endif if ((cnt = read (input->fd, input->ArgusReadPtr + input->ArgusReadSocketCnt, (input->ArgusReadSocketSize - input->ArgusReadSocketCnt))) > 0) { input->ArgusReadSocketCnt += cnt; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadCiscoStreamSocket (0x%x) read %d bytes, total %d need %d\n", input, cnt, input->ArgusReadSocketCnt, input->ArgusReadSocketSize); #endif if (input->ArgusReadSocketCnt == input->ArgusReadSocketSize) { switch (input->ArgusReadSocketState) { case ARGUS_READINGPREHDR: { unsigned short *sptr = (unsigned short *) input->ArgusReadPtr; input->ArgusReadCiscoVersion = ntohs(*sptr++); input->ArgusReadSocketNum = ntohs(*sptr); #define CISCO_VERSION_1 1 #define CISCO_VERSION_5 5 switch (input->ArgusReadCiscoVersion) { case CISCO_VERSION_1: input->ArgusReadSocketSize = sizeof(CiscoFlowHeaderV1_t) - 4; input->ArgusReadPtr = &input->ArgusReadBuffer[input->ArgusReadSocketCnt]; break; case CISCO_VERSION_5: input->ArgusReadSocketSize = sizeof(CiscoFlowHeaderV5_t) - 4; input->ArgusReadPtr = &input->ArgusReadBuffer[input->ArgusReadSocketCnt]; break; default: { fprintf (stderr, "input not Cisco wire format\n"); return(1); } } input->ArgusReadSocketState = ARGUS_READINGHDR; input->ArgusReadSocketCnt = 0; break; } case ARGUS_READINGHDR: { #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusReadCiscoStreamSocket (0x%x) read record header\n", input); #endif switch (input->ArgusReadCiscoVersion) { case CISCO_VERSION_1: { CiscoFlowHeaderV1_t *ArgusNetFlow = (CiscoFlowHeaderV1_t *) input->ArgusReadBuffer; CiscoFlowHeaderV1_t *nfptr = ArgusNetFlow; input->ArgusCiscoNetFlowParse = ArgusParseCiscoRecordV1; input->ArgusReadSocketSize = sizeof(CiscoFlowEntryV1_t); input->ArgusReadPtr = &input->ArgusReadBuffer[sizeof(CiscoFlowHeaderV1_t)]; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlowRecordHeader = (unsigned char *)ArgusNetFlow; break; } case CISCO_VERSION_5: { CiscoFlowHeaderV5_t *ArgusNetFlow = (CiscoFlowHeaderV5_t *) input->ArgusReadBuffer; CiscoFlowHeaderV5_t *nfptr = ArgusNetFlow; input->ArgusCiscoNetFlowParse = ArgusParseCiscoRecordV5; input->ArgusReadSocketSize = sizeof(CiscoFlowEntryV5_t); input->ArgusReadPtr = &input->ArgusReadBuffer[sizeof(CiscoFlowHeaderV5_t)]; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlow->flow_sequence = ntohl(nfptr->flow_sequence); ArgusNetFlowRecordHeader = (unsigned char *)ArgusNetFlow; break; } default: { #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusReadCiscoStreamSocket (0x%x) read header\n", input); #endif } } input->ArgusReadSocketState = ARGUS_READINGBLOCK; input->ArgusReadBlockPtr = input->ArgusReadPtr; input->ArgusReadSocketCnt = 0; break; } default: #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusReadCiscoStreamSocket (0x%x) read record complete\n", input); #endif if (ArgusHandleDatum (input->ArgusCiscoNetFlowParse (&input->ArgusReadPtr), &ArgusFilterCode)) return(1); if (!(--input->ArgusReadSocketNum)) { input->ArgusReadPtr = input->ArgusReadBuffer; bzero (input->ArgusReadBuffer, k_maxFlowPacketSize); input->ArgusReadSocketState = ARGUS_READINGPREHDR; input->ArgusReadSocketSize = 4; } else { switch (input->ArgusReadCiscoVersion) { case CISCO_VERSION_1: input->ArgusReadPtr = &input->ArgusReadBuffer[sizeof(CiscoFlowHeaderV1_t)]; break; case CISCO_VERSION_5: input->ArgusReadPtr = &input->ArgusReadBuffer[sizeof(CiscoFlowHeaderV5_t)]; break; default: { #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusReadCiscoStreamSocket (0x%x) read header\n", input); #endif } } } input->ArgusReadSocketCnt = 0; break; } } } else { #ifdef ARGUSDEBUG if (cnt < 0) ArgusDebug (3, "ArgusReadCiscoStreamSocket (0x%x) read returned %d error %s\n", input, cnt, strerror(errno)); else ArgusDebug (3, "ArgusReadCiscoStreamSocket (0x%x) read returned %d\n", input, cnt); #endif retn = 1; if ((cnt < 0) && ((errno == EAGAIN) || (errno == EINTR))) { retn = 0; } } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadCiscoStreamSocket (0x%x) returning %d\n", input, retn); #endif return (retn); } int ArgusCiscoDatagramSocketStart = 1; int ArgusReadCiscoDatagramSocket (struct ARGUS_INPUT *input) { int retn = 0, cnt = 0, count = 0, i = 0; unsigned short *sptr = NULL; unsigned char *ptr = NULL; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadCiscoDatagramSocket (0x%x) starting\n", input); #endif if ((cnt = read (input->fd, input->ArgusReadPtr, input->ArgusReadSocketSize)) > 0) { input->ArgusReadSocketCnt = cnt; sptr = (unsigned short *) input->ArgusReadPtr; ptr = (unsigned char *) input->ArgusReadPtr; #ifdef ARGUSDEBUG ArgusDebug (8, "ArgusReadCiscoDatagramSocket (0x%x) read %d bytes, capacity %d\n", input, cnt, input->ArgusReadSocketCnt, input->ArgusReadSocketSize); #endif #define CISCO_VERSION_1 1 #define CISCO_VERSION_5 5 #define CISCO_VERSION_6 6 #define CISCO_VERSION_8 8 switch (input->ArgusReadCiscoVersion = ntohs(*sptr)) { case CISCO_VERSION_1: { CiscoFlowHeaderV1_t *ArgusNetFlow = (CiscoFlowHeaderV1_t *) ptr; CiscoFlowHeaderV1_t *nfptr = (CiscoFlowHeaderV1_t *) sptr; input->ArgusCiscoNetFlowParse = ArgusParseCiscoRecordV1; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlowRecordHeader = ptr; ptr = (unsigned char *) (nfptr + 1); count = ArgusNetFlow->count; } break; case CISCO_VERSION_5: { CiscoFlowHeaderV5_t *ArgusNetFlow = (CiscoFlowHeaderV5_t *) ptr; CiscoFlowHeaderV5_t *nfptr = (CiscoFlowHeaderV5_t *) sptr; input->ArgusCiscoNetFlowParse = ArgusParseCiscoRecordV5; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlow->flow_sequence = ntohl(nfptr->flow_sequence); ArgusNetFlowRecordHeader = ptr; ptr = (unsigned char *) (nfptr + 1); count = ArgusNetFlow->count; } break; case CISCO_VERSION_6: { CiscoFlowHeaderV6_t *ArgusNetFlow = (CiscoFlowHeaderV6_t *) ptr; CiscoFlowHeaderV6_t *nfptr = (CiscoFlowHeaderV6_t *) sptr; input->ArgusCiscoNetFlowParse = ArgusParseCiscoRecordV6; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlow->flow_sequence = ntohl(nfptr->flow_sequence); ArgusNetFlowRecordHeader = ptr; ptr = (unsigned char *) (nfptr + 1); count = ArgusNetFlow->count; } break; case CISCO_VERSION_8: { CiscoFlowHeaderV8_t *ArgusNetFlow = (CiscoFlowHeaderV8_t *) ptr; CiscoFlowHeaderV8_t *nfptr = (CiscoFlowHeaderV8_t *) sptr; ArgusNetFlow->version = ntohs(nfptr->version); ArgusNetFlow->count = ntohs(nfptr->count); ArgusNetFlow->sysUptime = ntohl(nfptr->sysUptime); ArgusNetFlow->unix_secs = ntohl(nfptr->unix_secs); ArgusNetFlow->unix_nsecs = ntohl(nfptr->unix_nsecs); ArgusNetFlow->flow_sequence = ntohl(nfptr->flow_sequence); ArgusNetFlowRecordHeader = ptr; ptr = (unsigned char *) (nfptr + 1); count = ArgusNetFlow->count; if ((input->ArgusCiscoNetFlowParse = ArgusLookUpNetFlow(input, ArgusNetFlow->agg_method)) != NULL) { } } break; } for (i = 0; i < count; i++) { if (ArgusHandleDatum (input->ArgusCiscoNetFlowParse (&ptr), &ArgusFilterCode)) return(1); } } else { #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadCiscoDatagramSocket (0x%x) read returned %d error %s\n", input, cnt, strerror(errno)); #endif if ((cnt < 0) && ((errno == EAGAIN) || (errno == EINTR))) { retn = 0; } else retn = 1; } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadCiscoDatagramSocket (0x%x) returning %d\n", input, retn); #endif return (retn); } void ArgusReadStream () { int retn = 0, width = -1, i; struct timeval now, wait, timeoutValue; struct ARGUS_INPUT *input = NULL; fd_set readmask; if (ArgusRemoteFDs[0] == NULL) { #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusReadStream() ArgusRemoteFDs is empty\n"); #endif return; } if (gettimeofday (&now, NULL) == 0) { ArgusAdjustGlobalTime(&now); FD_ZERO (&readmask); for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) if (ArgusRemoteFDs[i] != NULL) { FD_SET (ArgusRemoteFDs[i]->fd, &readmask); width = (width < ArgusRemoteFDs[i]->fd) ? ArgusRemoteFDs[i]->fd : width; } width++; wait.tv_sec = 0; wait.tv_usec = 250000; #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusReadStream() starting\n"); #endif for (;;) { if ((retn = select (width, &readmask, NULL, NULL, &wait)) >= 0) { for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) { if ((input = ArgusRemoteFDs[i]) != NULL) { if (FD_ISSET (input->fd, &readmask)) { ArgusInput = input; switch (input->status & (ARGUS_DATA_SOURCE | ARGUS_CISCO_DATA_SOURCE)) { case ARGUS_DATA_SOURCE: #ifdef ARGUS_SASL if (input->sasl_conn && (input->sasl_conn->oparams.decode != NULL)) { if (ArgusReadSaslStreamSocket (input)) { ArgusCloseInput(input); ArgusRemoteFDs[i] = NULL; } } else #endif if (ArgusReadStreamSocket (input)) { ArgusCloseInput(input); ArgusRemoteFDs[i] = NULL; } break; case ARGUS_CISCO_DATA_SOURCE: if (ArgusRemoteHostList) if (ArgusReadCiscoDatagramSocket (input)) { ArgusCloseInput(input); ArgusRemoteFDs[i] = NULL; } if (ArgusInputFileList) if (ArgusReadCiscoStreamSocket (input)) { ArgusCloseInput(input); ArgusRemoteFDs[i] = NULL; } break; } } } } if (Sflag) { gettimeofday (&now, NULL); ArgusAdjustGlobalTime(&now); } else now = ArgusGlobalTime; if (timeoutValue.tv_sec == 0) { timeoutValue = ArgusGlobalTime; timeoutValue.tv_sec += RaClientTimeout.tv_sec; timeoutValue.tv_usec += RaClientTimeout.tv_usec; if (timeoutValue.tv_usec >= 1000000) { timeoutValue.tv_sec += 1; timeoutValue.tv_usec -= 1000000; } } if ((now.tv_sec > timeoutValue.tv_sec) || ((now.tv_sec == timeoutValue.tv_sec) && (now.tv_usec > timeoutValue.tv_usec))) { ArgusClientTimeout (); if (Tflag) { if ((Tflag - 1) == 0) { ArgusShutDown(0); } Tflag--; } timeoutValue = now; timeoutValue.tv_sec += RaClientTimeout.tv_sec; timeoutValue.tv_usec += RaClientTimeout.tv_usec; } width = -1; FD_ZERO (&readmask); for (i = 0; i < ARGUS_MAX_REMOTE_CONN; i++) if (ArgusRemoteFDs[i] != NULL) { FD_SET (ArgusRemoteFDs[i]->fd, &readmask); width = (width < ArgusRemoteFDs[i]->fd) ? ArgusRemoteFDs[i]->fd : width; } if (width < 0) return; else width++; wait.tv_sec = 0; wait.tv_usec = 250000; } else { #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadStream() select returned %s\n", strerror(errno)); #endif if (errno != EINTR) break; } } } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusReadStream() returning\n"); #endif } void ArgusProcessRecord (struct ArgusRecord *ptr) { if (ptr->ahdr.type & ARGUS_MAR) process_man (ptr); else { switch (ptr->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: switch (ptr->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: process_tcp (ptr); break; case IPPROTO_UDP: process_udp (ptr); break; case IPPROTO_ICMP: process_icmp (ptr); break; default: process_ip (ptr); break; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: process_arp (ptr); break; default: process_non_ip (ptr); break; } } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusProcessRecord (0x%x) returning\n", ptr); #endif } #include extern void ArgusLog (int, char *, ...); #define ARGUS_DEFAULTCISCOPORT 9995 char *ArgusRecordType = NULL; extern int ArgusInitializeAuthentication(void); #include #include int ArgusGetServerSocket (struct ARGUS_INPUT *input) { int retn = -1; struct sockaddr_in server; struct servent *sp; struct hostent *hp; int s, type = 0; unsigned short portnum = 0; switch (input->status & (ARGUS_DATA_SOURCE | ARGUS_CISCO_DATA_SOURCE)) { case ARGUS_DATA_SOURCE: { ArgusRecordType = "Argus"; type = SOCK_STREAM; if (!input->portnum) { if (!ArgusPortNum) { if ((sp = getservbyname ("monitor", "tcp")) != NULL) portnum = sp->s_port; else portnum = htons(ARGUS_DEFAULTPORT); } else portnum = htons(ArgusPortNum); input->portnum = ntohs(portnum); } else portnum = htons(input->portnum); break; } case ARGUS_CISCO_DATA_SOURCE: { struct ArgusRecord argus; ArgusRecordType = "Netflow"; type = SOCK_DGRAM; if (!input->portnum) { if (!ArgusPortNum) portnum = htons(ARGUS_DEFAULTCISCOPORT); else portnum = htons(ArgusPortNum); input->portnum = ntohs(portnum); } else portnum = htons(input->portnum); bzero ((char *)&argus, sizeof(argus)); argus.ahdr.type = ARGUS_MAR | ARGUS_CISCO_NETFLOW; argus.ahdr.length = sizeof (argus); argus.ahdr.cause = ARGUS_START; argus.ahdr.argusid = ARGUS_COOKIE; argus.argus_mar.startime.tv_sec = ArgusGlobalTime.tv_sec; argus.argus_mar.now.tv_sec = ArgusGlobalTime.tv_sec; argus.argus_mar.major_version = major_version; argus.argus_mar.minor_version = minor_version; argus.argus_mar.record_len = -1; input->major_version = argus.argus_mar.major_version; input->minor_version = argus.argus_mar.minor_version; bcopy ((char *) &argus, (char *)&input->ArgusInitCon, sizeof (argus)); bcopy ((char *) &argus, (char *) ArgusOriginal, sizeof(argus)); ArgusInput = input; break; } default: ArgusLog (LOG_ERR, "ArgusGetServerSocket(0x%x) unknown type\n", input); } bzero ((char *) &server, sizeof (server)); if ((s = socket (AF_INET, type, 0)) >= 0) { if (type == SOCK_DGRAM) { server.sin_addr.s_addr = INADDR_ANY; server.sin_family = AF_INET; server.sin_port = portnum; fprintf (stderr, "%s: Binding port %d Expecting %s records\n", ArgusProgramName, ntohs(portnum), ArgusRecordType); if ((bind (s, (struct sockaddr *)&server, sizeof(server))) < 0) ArgusLog (LOG_ERR, "bind (%d, %s:%hu, %d) failed %s\n", s, inet_ntoa(server.sin_addr), server.sin_port, sizeof(server), strerror(errno)); } else { int optval = 1; if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(int)) < 0) { #ifdef ARGUSDEBUG ArgusDebug (2, "setsockopt(%d, SOL_SOCKET, SO_KEEPALIVE, 0x%x, %d) failed:", s, optval, sizeof(int)); #endif } if ((hp = gethostbyaddr ((char *)&input->addr, sizeof (input->addr), AF_INET)) != NULL) { bcopy ((char *) hp->h_addr, (char *)&server.sin_addr, hp->h_length); server.sin_family = hp->h_addrtype; server.sin_port = portnum; fprintf (stderr, "%s: Trying %s port %d Expecting %s records\n", ArgusProgramName, (hp->h_name) ? (hp->h_name) : intoa (input->addr), ntohs(portnum), ArgusRecordType); } else { server.sin_addr.s_addr = input->addr; server.sin_family = AF_INET; server.sin_port = portnum; fprintf (stderr, "%s: Trying %s port %d Expecting %s records\n", ArgusProgramName, intoa (input->addr), ntohs(portnum), ArgusRecordType); } if ((connect (s, (struct sockaddr *)&server, sizeof(server))) < 0) ArgusLog (LOG_ERR, "connect (%d, %s:%hu, %d) failed %s\n", s, inet_ntoa(server.sin_addr), server.sin_port, sizeof(server), strerror(errno)); } retn = s; input->fd = s; if (type == SOCK_DGRAM) fprintf (stderr, "%s: receiving\n", ArgusProgramName); else fprintf (stderr, "%s: connected\n", ArgusProgramName); } else { fprintf (stderr, "%s: socket() failed. %s\n", ArgusProgramName, strerror(errno)); } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusGetServerSocket (0x%x) returning %d\n", input, retn); #endif return (retn); } int ArgusAddFileList (char *ptr) { register int retn = 0; register struct ARGUS_INPUT *file, *list; if (ptr) { if ((file = (struct ARGUS_INPUT *) ArgusCalloc (1, sizeof(struct ARGUS_INPUT))) != NULL) { if ((list = ArgusInputFileList) != NULL) { while (list->nxt) list = list->nxt; list->nxt = file; } else ArgusInputFileList = file; file->filename = strdup(ptr); file->status |= (Cflag ? ARGUS_CISCO_DATA_SOURCE : ARGUS_DATA_SOURCE); retn = 1; } } #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusAddFileList (%s) returning %d\n", ptr, retn); #endif return (retn); } void ArgusDeleteFileList () { struct ARGUS_INPUT *addr = ArgusInputFileList; while (addr) { if (addr->filename) free(addr->filename); addr = addr->nxt; ArgusFree(ArgusInputFileList); ArgusInputFileList = addr; } #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusDeleteFileList () returning\n"); #endif } #include #include #include int ArgusAddHostList (char *str) { int retn = 0; struct ARGUS_INPUT *addr = NULL; unsigned int ipaddr, **name; long int portnum = 0; char *ptr = NULL, *endptr = NULL; if ((ptr = strchr (str, (int)':')) != NULL) { *ptr++ = '\0'; portnum = strtol(ptr, &endptr, 10); if (endptr == ptr) usage(); } if ((ipaddr = (unsigned int) inet_addr (str)) == (unsigned int) -1) { if ((name = (unsigned int **) argus_nametoaddr (str)) != NULL) { if (*name) { if ((addr = (struct ARGUS_INPUT *) ArgusCalloc (1, sizeof (struct ARGUS_INPUT))) != NULL) { addr->nxt = ArgusRemoteHostList; ArgusRemoteHostList = addr; addr->addr = ntohl(**name); addr->hostname = strdup(str); addr->portnum = portnum; retn = 1; } } } } else if ((addr = (struct ARGUS_INPUT *) ArgusCalloc (1, sizeof (struct ARGUS_INPUT))) != NULL) { addr->nxt = ArgusRemoteHostList; ArgusRemoteHostList = addr; addr->addr = ipaddr; addr->portnum = portnum; retn = 1; } if (addr) addr->status |= (Cflag ? ARGUS_CISCO_DATA_SOURCE : ARGUS_DATA_SOURCE); #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusAddHostList (%s) returning %d\n", str, retn); #endif return (retn); } void ArgusDeleteHostList () { struct ARGUS_INPUT *addr = ArgusRemoteHostList; while (addr) { if (addr->hostname) free(addr->hostname); addr = addr->nxt; ArgusFree(ArgusRemoteHostList); ArgusRemoteHostList = addr; } #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusDeleteHostList () returning\n"); #endif } #include #include #include int ArgusWriteNewLogfile (char *file, struct ArgusRecord *argus) { int retn = 0, fd; struct stat buf; if (file) { if (strcmp (file, "-")) { if ((fd = open (file, O_WRONLY|O_CREAT|O_APPEND, 0644)) >= 0) { if (fstat (fd, &buf) >= 0) { if (buf.st_size == 0) if ((write (fd, (char *)&ArgusInput->ArgusInitCon, ntohs(ArgusInput->ArgusInitCon.ahdr.length))) < 0) ArgusLog (LOG_ERR, "ArgusWriteNewLogfile(%s, 0x%x) write error %s", file, argus, strerror(errno)); } else { ArgusLog (LOG_ERR, "ArgusWriteNewLogfile(%s, 0x%x) fstat error %s", file, argus, strerror(errno)); } if (argus != NULL) { if ((write (fd, argus, ntohs(argus->ahdr.length))) < 0) ArgusLog (LOG_ERR, "ArgusWriteNewLogfile(%s, 0x%x) write error %s", file, argus, strerror(errno)); } close (fd); } else { ArgusLog (LOG_ERR, "ArgusWriteNewLogfile(%s, 0x%x) open error %s", file, argus, strerror(errno)); } if (firstWrite) firstWrite = 0; } else { if (firstWrite) { if (!(fwrite ((char *)&ArgusInput->ArgusInitCon, ntohs(ArgusInput->ArgusInitCon.ahdr.length), 1, stdout))) ArgusLog (LOG_ERR, "ArgusWriteNewLogfile(%s, 0x%x) fwrite error %s", file, argus, strerror(errno)); fflush (stdout); firstWrite = 0; } if (argus) { if (!(fwrite (argus, ntohs(argus->ahdr.length), 1, stdout))) retn++; fflush (stdout); } } } #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusWriteNewLogFile (%s, 0x%x) returning %d\n", file, argus, retn); #endif return (retn); } int check_time (struct ArgusRecord *ptr) { struct tm tmbuf, *tm; int retn = 0; struct timeval *start, *last, lastbuf; if (ptr->ahdr.type & ARGUS_MAR) { start = &ptr->argus_mar.startime; last = &ptr->argus_mar.now; if (!(start->tv_sec)) start = &ptr->argus_mar.now; } else { start = &ptr->argus_far.time.start; last = &ptr->argus_far.time.last; if (ArgusThisFarStatus & ARGUS_AGR_DSR_STATUS) { lastbuf = ((struct ArgusAGRStruct *)ArgusThisFarHdrs[ARGUS_AGR_DSR_INDEX])->lasttime; } } ArgusGlobalTime = *last; gettimeofday (&ArgusNowTime, 0L); if ((tm = localtime ((time_t *)&start->tv_sec)) != NULL) bcopy ((char *) tm, (char *)&tm_startime, sizeof (struct tm)); else bzero ((char *)&tm_startime, sizeof (struct tm)); if ((tm = localtime ((time_t *)&last->tv_sec)) != NULL) bcopy ((char *) tm, (char *)&tm_lasttime, sizeof (struct tm)); else bzero ((char *)&tm_startime, sizeof (struct tm)); if (tflag) { time_t *sec; if (!explicit_date) { sec = (time_t *)&start->tv_sec; tm = localtime(sec); if (tm->tm_yday != starTimeFilter.tm_yday) { bcopy ((char *) tm, (char *) &tmbuf, sizeof (struct tm)); if (check_time_format (&tmbuf, timearg)) ArgusLog (LOG_ERR, "time syntax error %s\n", timearg); } } if (ptr->ahdr.type & ARGUS_MAR) { if (ptr->ahdr.status & ARGUS_START) { if ((ptr->argus_mar.now.tv_sec >= startime_t) && (ptr->argus_mar.now.tv_sec <= lasttime_t)) retn++; } else { if ((ptr->argus_mar.now.tv_sec >= startime_t) && (ptr->argus_mar.now.tv_sec <= lasttime_t)) retn++; } } else { if (((start->tv_sec >= startime_t) && (start->tv_sec <= lasttime_t)) || ((last->tv_sec >= startime_t) && (last->tv_sec <= lasttime_t)) || ((start->tv_sec < startime_t) && (last->tv_sec > lasttime_t))) retn++; } } else retn++; return (retn); } #include int parseUserDataArg (char **arg, char *args[], int ind) { int retn = -1; char buf[64], *ptr = buf; bzero (buf, 64); strcpy (buf, *arg); ptr += strlen (buf); if ((ptr = strchr(*arg, ':')) && (*(ptr + 1) != '\0')) { retn = 0; } else { if (args) { if (args[ind] && (*args[ind] == ':')) { if (strlen (args[ind]) == 1) { strcat (buf, ":"); strcat (buf, args[ind + 1]); retn = 2; } else { ptr = args[ind]; if (isdigit((int)*(ptr + 1))) { strcat (buf, args[ind]); retn = 1; } else retn = 0; } } else retn = 0; } else retn = 0; } *arg = savestr(buf); if ((ptr = strchr (buf, ':')) != NULL) { ptr++; if (*buf == 's') ArgusSrcUserDataLen = atoi(buf + 1); else ArgusLog (LOG_ERR, "user data syntax error %s\n", buf); if (*ptr == 'd') ArgusDstUserDataLen = atoi(ptr + 1); else ArgusLog (LOG_ERR, "user data syntax error %s\n", buf); } else { if (isdigit((int)*buf)) { ArgusSrcUserDataLen = atoi(buf); ArgusDstUserDataLen = atoi(buf); } else { if (*buf == 's') ArgusSrcUserDataLen = atoi(buf + 1); if (*buf == 'd') ArgusDstUserDataLen = atoi(buf + 1); } } if (retn < 0) ArgusLog (LOG_ERR, "user data syntax error %s\n", buf); return (retn); } int parseTimeArg ( char **arg, char *args[], int ind, struct tm *tm) { int retn = -1; char buf[64], *ptr = buf; bzero (buf, 64); strcpy (buf, *arg); ptr += strlen (buf); if ((ptr = strchr(*arg, '-')) && (*(ptr + 1) != '\0')) { retn = 0; } else { if (args) { if (args[ind] && (*args[ind] == '-')) { if (strlen (args[ind]) == 1) { strcat (buf, "-"); strcat (buf, args[ind + 1]); retn = 2; } else { ptr = args[ind]; if (isdigit((int)*(ptr + 1))) { strcat (buf, args[ind]); retn = 1; } else retn = 0; } } else retn = 0; } } if ((ptr = strchr(*arg, '.')) || (ptr = strchr(*arg, '/'))) explicit_date++; if (check_time_format (tm, buf)) ArgusLog (LOG_ERR, "time syntax error %s\n", buf); *arg = savestr(buf); return (retn); } #define ARGUS_YEAR 1 #define ARGUS_MONTH 2 #define ARGUS_DAY 3 #define ARGUS_HOUR 4 #define ARGUS_MIN 5 #define ARGUS_SEC 6 int RaDaysInAMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int check_time_format (struct tm *tm, char *str) { int retn = 0; char *ptr, buf[64]; /*[[[yyyy/]mm/]dd.]hh[:mm[:ss]] - [[[yyyy/]mm/]dd.]hh[:mm[:ss]]*/ strcpy (buf, str); if ((ptr = strchr(buf, '-')) != NULL) { *ptr = '\0'; if ((retn = parseTime (&starTimeFilter, tm, buf)) > 0) if ((retn = parseTime (&lastTimeFilter, &starTimeFilter, ptr + 1)) > 0) retn = 0; } else { if ((retn = parseTime (&starTimeFilter, tm, buf)) > 0) { bcopy ((char *)&starTimeFilter, (char *)&lastTimeFilter, sizeof(struct tm)); switch (retn) { case ARGUS_YEAR: lastTimeFilter.tm_year++; break; case ARGUS_MONTH: lastTimeFilter.tm_mon++; break; case ARGUS_DAY: lastTimeFilter.tm_mday++; break; case ARGUS_HOUR: lastTimeFilter.tm_hour++; break; case ARGUS_MIN: lastTimeFilter.tm_min++; break; case ARGUS_SEC: lastTimeFilter.tm_sec++; break; } while (tm->tm_sec > 59) {tm->tm_min++; tm->tm_sec -= 60;} while (tm->tm_min > 59) {tm->tm_hour++; tm->tm_min -= 60;} while (tm->tm_hour > 23) {tm->tm_mday++; tm->tm_hour -= 24;} while (tm->tm_mday > RaDaysInAMonth[tm->tm_mon]) {tm->tm_mday -= RaDaysInAMonth[tm->tm_mon]; tm->tm_mon++;} while (tm->tm_mon > 11) {tm->tm_year++; tm->tm_mon -= 12;} retn = 0; } } if (retn == 0) { startime_t = timelocal (&starTimeFilter); lasttime_t = timelocal (&lastTimeFilter); if (!(lasttime_t >= startime_t)) { fprintf (stderr, "error: invalid time range\n"); retn++; } } return (retn); } int parseTime (struct tm *tm, struct tm *ctm, char *str) { char *hptr = NULL, *dptr = NULL, *mptr = NULL, *yptr = NULL; char *minptr = NULL, *secptr = NULL, *ptr; int retn = 0, hour = 0, mins = 0, sec = 0, i; time_t thistime; /*[[[yyyy/]mm/]dd].]hh[:mm[:ss]]*/ bcopy ((u_char *) ctm, (u_char *) tm, sizeof (struct tm)); if ((hptr = strchr (str, '.')) != NULL) { *hptr++ = '\0'; if (!(isdigit((int)*hptr))) return -1; } if ((dptr = strrchr (str, '/')) != NULL) { /* mm/dd */ /* ^ */ *dptr++ = '\0'; if ((mptr = strrchr (str, '/')) != NULL) { /* yyyy/mm/dd */ /* ^ */ *mptr++ = '\0'; yptr = str; } else mptr = str; } else { if (hptr != NULL) dptr = str; else hptr = str; } if (yptr) { if (strlen(yptr) != 4) return -1; for (ptr = yptr, i = 0; i < strlen(yptr); i++) if (!(isdigit((int)*ptr++))) return -1; tm->tm_year = atoi(yptr) - 1900; retn = ARGUS_YEAR; } if (mptr) { if (strlen(mptr) != 2) return -1; for (ptr = mptr, i = 0; i < strlen(mptr); i++) if (!(isdigit((int)*ptr++))) return -1; tm->tm_mon = atoi(mptr) - 1; retn = ARGUS_MONTH; } if (dptr) { if (strlen(dptr) != 2) return -1; for (ptr = dptr, i = 0; i < strlen(dptr); i++) if (!(isdigit((int)*ptr++))) return -1; tm->tm_mday = atoi(dptr); retn = ARGUS_DAY; } if (hptr) { if ((minptr = strchr (hptr, ':')) != NULL) { *minptr++ = '\0'; if ((secptr = strchr (minptr, ':')) != NULL) { *secptr++ = '\0'; } } for (ptr = hptr, i = 0; i < strlen(hptr); i++) if (!(isdigit((int)*ptr++))) return -1; hour = atoi(hptr); retn = ARGUS_HOUR; if (minptr != NULL) { for (ptr = minptr, i = 0; i < strlen(minptr); i++) if (!(isdigit((int)*ptr++))) return -1; mins = atoi(minptr); retn = ARGUS_MIN; } if (secptr != NULL) { for (ptr = secptr, i = 0; i < strlen(secptr); i++) if (!(isdigit((int)*ptr++))) return -1; sec = atoi(secptr); retn = ARGUS_SEC; } } tm->tm_hour = hour; tm->tm_min = mins; tm->tm_sec = sec; #if !defined(HAVE_SOLARIS) && !defined(__sgi) && !defined(linux) && !defined(AIX) && !defined(CYGWIN) tm->tm_zone = NULL; tm->tm_gmtoff = 0; #endif if (tm->tm_year < 0) retn = -1; if ((tm->tm_mon > 11) || (tm->tm_mon < 0)) retn = -1; if ((tm->tm_mday > 31) || (tm->tm_mday < 0)) retn = -1; if ((tm->tm_hour > 23) || (tm->tm_hour < 0)) retn = -1; if ((tm->tm_min > 60) || (tm->tm_min < 0)) retn = -1; if ((tm->tm_sec > 60) || (tm->tm_sec < 0)) retn = -1; if (retn >= 0) { thistime = timelocal (tm); tm = localtime ((time_t *)&thistime); } return (retn); } #define ARGUS_RCITEMS 41 #define RA_ARGUS_SERVER 0 #define RA_CISCONETFLOW_SOURCE 1 #define RA_ARGUS_SERVERPORT 2 #define RA_INPUT_FILE 3 #define RA_NO_OUTPUT 4 #define RA_USER_AUTH 5 #define RA_AUTH_PASS 6 #define RA_OUTPUT_FILE 7 #define RA_EXCEPTION_OUTPUT_FILE 8 #define RA_TIMERANGE 9 #define RA_RUNTIME 10 #define RA_FLOW_MODEL 11 #define RA_FIELD_DELIMITER 12 #define RA_TIME_FORMAT 13 #define RA_USEC_PRECISION 14 #define RA_PRINT_LABELS 15 #define RA_PRINT_SUMMARY 16 #define RA_PRINT_ARGUSID 17 #define RA_PRINT_MACADDRS 18 #define RA_PRINT_HOSTNAMES 19 #define RA_PRINT_LOCALONLY 20 #define RA_PRINT_COUNTS 21 #define RA_PRINT_APPLICATION_BYTES 22 #define RA_PRINT_RESPONSE_DATA 23 #define RA_PRINT_UNIX_TIME 24 #define RA_PRINT_STARTIME 25 #define RA_PRINT_LASTIME 26 #define RA_PRINT_INDICATORS 27 #define RA_PRINT_DURATION 28 #define RA_PRINT_TCPSTATES 29 #define RA_PRINT_TCPFLAGS 30 #define RAGATOR_TIME_SERIES 31 #define RAGATOR_VALIDATE 32 #define RAMON_MODE 33 #define RAMON_NUMBER 34 #define RA_DEBUG_LEVEL 35 #define RA_PRINT_USERDATA 36 #define RA_USERDATA_ENCODE 37 #define RA_FILTER 38 #define RA_HOST_FIELD_LENGTH 39 #define RA_PORT_FIELD_LENGTH 40 char *ArgusResourceFileStr [] = { "RA_ARGUS_SERVER=", "RA_CISCONETFLOW_SOURCE=", "RA_ARGUS_SERVERPORT=", "RA_INPUT_FILE=", "RA_NO_OUTPUT=", "RA_USER_AUTH=", "RA_AUTH_PASS=", "RA_OUTPUT_FILE=", "RA_EXCEPTION_OUTPUT_FILE=", "RA_TIMERANGE=", "RA_RUN_TIME=", "RA_FLOW_MODEL=", "RA_FIELD_DELIMITER=", "RA_TIME_FORMAT=", "RA_USEC_PRECISION=", "RA_PRINT_LABELS=", "RA_PRINT_SUMMARY=", "RA_PRINT_ARGUSID=", "RA_PRINT_MACADDRS=", "RA_PRINT_HOSTNAMES=", "RA_PRINT_LOCALONLY=", "RA_PRINT_COUNTS=", "RA_PRINT_APPLICATION_BYTES=", "RA_PRINT_RESPONSE_DATA=", "RA_PRINT_UNIX_TIME=", "RA_PRINT_STARTIME=", "RA_PRINT_LASTIME=", "RA_PRINT_INDICATORS=", "RA_PRINT_DURATION=", "RA_PRINT_TCPSTATES=", "RA_PRINT_TCPFLAGS=", "RAGATOR_TIME_SERIES=", "RAGATOR_VALIDATE=", "RAMON_MODE=", "RAMON_NUMBER=", "RA_DEBUG_LEVEL=", "RA_PRINT_USERDATA=", "RA_USERDATA_ENCODE=", "RA_FILTER=", "RA_HOST_FIELD_LENGTH=", "RA_PORT_FIELD_LENGTH=", }; #include int ArgusParseResourceFile (char *file) { int retn = 0, i, len, Soption = 0, roption = 0, found = 0, lines = 0; char strbuf[MAXSTRLEN], *str = strbuf, *optarg = NULL, *ptr = NULL; FILE *fd; if (file) { if ((fd = fopen (file, "r")) != NULL) { retn = 1; while ((fgets(str, MAXSTRLEN, fd)) != NULL) { lines++; while (*str && isspace((int)*str)) str++; if (*str && (*str != '#') && (*str != '\n') && (*str != '!')) { found = 0; for (i = 0; i < ARGUS_RCITEMS; i++) { len = strlen(ArgusResourceFileStr[i]); if (!(strncmp (str, ArgusResourceFileStr[i], len))) { optarg = &str[len]; if (optarg[strlen(optarg) - 1] == '\n') optarg[strlen(optarg) - 1] = '\0'; if (*optarg == '\"') optarg++; if (optarg[strlen(optarg) - 1] == '\"') optarg[strlen(optarg) - 1] = '\0'; if (*optarg == '\0') optarg = NULL; if (optarg) { switch (i) { case RA_ARGUS_SERVER: ++Sflag; if (!Soption++ && (ArgusRemoteHostList != NULL)) ArgusDeleteHostList(); if (!(ArgusAddHostList (optarg))) { fprintf (stderr, "%s: host %s unknown\n", ArgusProgramName, optarg); exit (1); } break; case RA_CISCONETFLOW_SOURCE: ++Sflag; ++Cflag; if (!Soption++ && (ArgusRemoteHostList != NULL)) ArgusDeleteHostList(); if (!(ArgusAddHostList (optarg))) { fprintf (stderr, "%s: host %s unknown\n", ArgusProgramName, optarg); exit (1); } break; case RA_ARGUS_SERVERPORT: ArgusPortNum = atoi (optarg); break; break; case RA_INPUT_FILE: if ((!roption++) && (ArgusInputFileList != NULL)) ArgusDeleteFileList(); if (!(ArgusAddFileList (optarg))) { fprintf (stderr, "%s: error: file arg %s\n", ArgusProgramName, optarg); exit (1); } break; case RA_NO_OUTPUT: if (!(strncasecmp(optarg, "yes", 3))) qflag++; else qflag = 0; break; case RA_USER_AUTH: ustr = strdup(optarg); break; case RA_AUTH_PASS: pstr = strdup(optarg); break; case RA_OUTPUT_FILE: wfile = strdup(optarg); break; case RA_EXCEPTION_OUTPUT_FILE: exceptfile = optarg; break; case RA_TIMERANGE: if ((parseTimeArg (&timearg, NULL, 0, RaTmStruct)) < 0) usage (); break; case RA_RUNTIME: Tflag = atoi (optarg); break; case RA_FIELD_DELIMITER: ptr = optarg; if ((ptr = strchr (optarg, '\'')) != NULL) { ptr++; if (ptr[0] == '\'') break; } if (ptr[0] == '\\') { switch (ptr[1]) { case 'a': RaFieldDelimiter = '\a'; break; case 'b': RaFieldDelimiter = '\b'; break; case 't': RaFieldDelimiter = '\t'; break; case 'n': RaFieldDelimiter = '\n'; break; case 'v': RaFieldDelimiter = '\v'; break; case 'f': RaFieldDelimiter = '\f'; break; case 'r': RaFieldDelimiter = '\r'; break; case '\\': RaFieldDelimiter = '\\'; break; } if (RaFieldDelimiter != '\0') break; } else RaFieldDelimiter = *ptr; break; case RA_TIME_FORMAT: RaTimeFormat = strdup(optarg); case RA_USEC_PRECISION: pflag = atoi (optarg); break; case RA_PRINT_SUMMARY: if (!(strncasecmp(optarg, "yes", 3))) aflag = 1; else aflag = 0; break; case RA_PRINT_ARGUSID: if (!(strncasecmp(optarg, "yes", 3))) idflag = 1; else idflag = 0; break; case RA_PRINT_MACADDRS: if (!(strncasecmp(optarg, "yes", 3))) mflag = 1; else mflag = 0; break; case RA_PRINT_HOSTNAMES: if (!(strncasecmp(optarg, "yes", 3))) nflag = 0; else nflag = 1; break; case RA_PRINT_LOCALONLY: if (!(strncasecmp(optarg, "yes", 3))) ++fflag; else fflag = 0; break; case RA_FLOW_MODEL: ArgusFlowModelFile = strdup(optarg); break; case RA_PRINT_LABELS: switch (Lflag = atoi(optarg)) { case 0: Lflag = -1; break; case -1: Lflag = 0; break; } break; case RA_PRINT_COUNTS: if (!(strncasecmp(optarg, "yes", 3))) ++cflag; else cflag = 0; break; case RA_PRINT_APPLICATION_BYTES: if (!(strncasecmp(optarg, "yes", 3))) ++Aflag; else Aflag = 0; break; case RA_PRINT_RESPONSE_DATA: if (!(strncasecmp(optarg, "yes", 3))) Rflag++; else Rflag = 0; break; case RA_PRINT_UNIX_TIME: if (!(strncasecmp(optarg, "yes", 3))) ++uflag; else uflag = 0; break; case RA_PRINT_STARTIME: if (!(strncasecmp(optarg, "yes", 3))) ++RaPrintStartTime; else RaPrintStartTime = 0; break; case RA_PRINT_LASTIME: if (!(strncasecmp(optarg, "yes", 3))) ++RaPrintLastTime; else RaPrintLastTime = 0; break; case RA_PRINT_INDICATORS: if (!(strncasecmp(optarg, "yes", 3))) Iflag++; else Iflag = 0; break; case RA_PRINT_DURATION: if (!(strncasecmp(optarg, "yes", 3))) gflag++; break; case RA_PRINT_TCPSTATES: if (!(strncasecmp(optarg, "yes", 3))) zflag++; else zflag = 0; break; case RA_PRINT_TCPFLAGS: Zflag = *optarg; break; case RAGATOR_TIME_SERIES: if (!(strncasecmp(optarg, "yes", 3))) Hflag++; else Hflag = 0; break; case RAGATOR_VALIDATE: if (!(strncasecmp(optarg, "yes", 3))) Vflag++; else Vflag = 0; break; case RAMON_MODE: Mflag = optarg; break; case RAMON_NUMBER: Nflag = atoi (optarg); break; case RA_DEBUG_LEVEL: Argusdflag = (atoi(optarg)); break; case RA_PRINT_USERDATA: dflag++; if ((parseUserDataArg (&optarg, NULL, 0)) < 0) usage (); break; case RA_USERDATA_ENCODE: if (!(strncasecmp(optarg, "ascii", 5))) eflag = ARGUS_ENCODE_ASCII; else eflag = ARGUS_ENCODE_64; break; case RA_FILTER: { char *ptr; if ((RaInputFilter = ArgusCalloc (1, MAXSTRLEN)) != NULL) { ptr = RaInputFilter; str = optarg; while (*str) { if ((*str == '\\') && (str[1] == '\n')) { fgets(str, MAXSTRLEN, fd); while (*str && (isspace((int)*str) && (str[1] && isspace((int)str[1])))) str++; } if ((*str != '\n') && (*str != '"')) *ptr++ = *str++; else str++; } } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusParseResourceFile: ArgusFilter \"%s\" \n", RaInputFilter); #endif break; } case RA_HOST_FIELD_LENGTH: hfield = atoi (optarg); break; case RA_PORT_FIELD_LENGTH: pfield = atoi (optarg); break; } } found++; break; } } if (!found) { ArgusLog (LOG_ERR, "ArgusParseResourceFile (%s) syntax error line %d\n", file, lines); } } } } else { #ifdef ARGUSDEBUG ArgusDebug (1, "config file '%s' %s\n", file, strerror(errno)); #endif } if (RaPrintStartTime && RaPrintLastTime) Gflag++; else if (RaPrintLastTime) lflag++; } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusParseResourceFile (%s) returning %d\n", file, retn); #endif return (retn); }