/* * 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. * */ /* ArgusModeler.c * * Written by Carter Bullard * QoSient, LLC * Mon Aug 7 14:48:26 EDT 2000 * */ #ifndef ArgusModeler #define ArgusModeler #endif #include #include #include #include struct ArgusModelerStruct * ArgusNewModeler() { struct ArgusModelerStruct *retn = NULL; struct argtimeval tvpbuf, *tvp = &tvpbuf; if ((retn = (struct ArgusModelerStruct *) ArgusCalloc (1, sizeof (struct ArgusModelerStruct))) != NULL) { gettimeofday (tvp, 0L); ArgusGlobalTime = *tvp; } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusNewModeler() returning 0x%x\n", retn); #endif return (retn); } void ArgusInitModeler() { if ((ArgusHashTable.array = (struct ArgusHashTableHeader **) ArgusCalloc (ARGUS_HASHTABLESIZE, sizeof (struct ArgusHashTableHeader *))) != NULL) { ArgusHashTable.size = ARGUS_HASHTABLESIZE; } else ArgusLog (LOG_ERR, "ArgusInitModeler () ArgusCalloc error %s\n", strerror(errno)); ArgusModelerOutputSocket = ArgusNewSocket(ArgusOutputPipe[CLIENTSIDE]); ArgusFlowQueue = ArgusNewQueue(); #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusInitModeler(): ArgusHashArray 0x%x\n", ArgusHashTable.array); #endif } void ArgusDeleteModeler() { ArgusModelerCleanUp (); ArgusDeleteQueue (ArgusFlowQueue); if (ArgusModel) ArgusFree(ArgusModel); if (ArgusHashTable.array) ArgusFree(ArgusHashTable.array); if (ArgusModelerOutputSocket) { while (ArgusModelerOutputSocket->ArgusOutputList->count) if (ArgusWriteOutSocket(ArgusModelerOutputSocket) < 0) break; } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusDeleteModeler() ArgusModeler 0x%x, HashArray 0x%x\n", ArgusModel, ArgusHashTable.array); #endif } #include #if !defined(__OpenBSD__) #include #endif struct llc ArgusThisLLCBuffer; struct llc *ArgusThisLLC = &ArgusThisLLCBuffer; struct ether_header *ArgusProcessISL (struct ether_header *, int); void ArgusProcessIpxHdr (struct ether_header *, int); void ArgusProcessNetbeuiHdr (struct ether_header *, int); void ArgusProcessNetbiosHdr (struct ether_header *, int); void ArgusProcessIsoclnsHdr (struct ether_header *, int); #define ARGUS_IPX_TAG 100 void ArgusProcessIpxHdr (struct ether_header *ep, int length) { ArgusThisNetworkFlowType |= ARGUS_IPX_TAG; } #define ARGUS_ISL_ETHERHDR_LEN 26 struct ether_header * ArgusProcessISL (struct ether_header *ep, int length) { struct ether_header *retn = NULL; int type = (((unsigned char *)ep)[5] >> 4) & 0x0F; #define ARGUS_TYPE_ETHER 0x0 #define ARGUS_TYPE_TR 0x0 #define ARGUS_TYPE_FDDI 0x2 #define ARGUS_TYPE_ATM 0x3 switch (type) { case ARGUS_TYPE_ETHER: ep = (struct ether_header *) ((unsigned char *)ep + ARGUS_ISL_ETHERHDR_LEN); return (ArgusProcessEtherHdr(ep, length - ARGUS_ISL_ETHERHDR_LEN)); } return (retn); } void ArgusProcessNetbeuiHdr (struct ether_header *ep, int length) { } void ArgusProcessNetbiosHdr (struct ether_header *ep, int length) { } #define ARGUS_CLNS 129 #define ARGUS_ESIS 130 #define ARGUS_ISIS 131 #define ARGUS_NULLNS 132 void ArgusProcessIsoclnsHdr (struct ether_header *ep, int length) { unsigned char *ptr = (unsigned char *)ep; ptr += 3; switch (*ptr) { case ARGUS_CLNS: ArgusThisNetworkFlowType |= ARGUS_CLNS; break; case ARGUS_ESIS: ArgusThisNetworkFlowType |= ARGUS_ESIS; break; case ARGUS_ISIS: ArgusThisNetworkFlowType |= ARGUS_ISIS; break; case 0: ArgusThisNetworkFlowType |= ARGUS_NULLNS; break; default: ArgusThisNetworkFlowType |= ARGUS_CLNS; break; } ArgusThisLength -= sizeof(struct llc); ArgusSnapLength -= sizeof(struct llc); ArgusThisUpHdr = (ptr + sizeof(struct llc)); ArgusThisPacketLLCEncaps++; } unsigned short ArgusDiscoverNetworkProtocol (unsigned char *ptr) { unsigned short retn = ETHERTYPE_MPLS; struct ip *ip; if ((ip = (struct ip *) ptr) != NULL) { if (((ip->ip_v == 4) && (ip->ip_hl >= 5)) && (ntohs(ip->ip_len) >= 20)) { retn = ETHERTYPE_IP; } } return (retn); } void ArgusParseMPLSLabel (unsigned char *ptr, unsigned int *label, unsigned char *exp, unsigned char *bos, unsigned char *ttl) { *label = (ptr[0] << 12) | (ptr[1] << 4) | ((ptr[2] >> 4) & 0xff); *exp = (ptr[2] >> 1) & 0x07; *bos = (ptr[2] & 0x01); *ttl = ptr[3]; } struct ether_header * ArgusProcessEtherHdr (struct ether_header *ep, int length) { unsigned char *ptr; struct ether_header *retn = ep; unsigned short proto; int len = sizeof(struct ether_header); #ifdef _LITTLE_ENDIAN ep->ether_type = ntohs (ep->ether_type); #endif ArgusThisPacketLLCEncaps = 0; ArgusThisPacketMPLSEncaps = 0; ArgusThisPacket8021QEncaps = 0; ArgusThisPacketPPPoEEncaps = 0; length -= len; ArgusThisLength -= len; ArgusSnapLength -= len; ArgusThisNetworkFlowType = ep->ether_type; ArgusThisUpHdr = (unsigned char *) (ep + 1); ArgusThisMac->type = ARGUS_MAC_DSR; ArgusThisMac->length = sizeof(*ArgusThisMac); ArgusThisMac->status = ep->ether_type; bcopy((char *)&ep->ether_shost, (char *)&ArgusThisMac->phys_union.ether.ethersrc, 6); bcopy((char *)&ep->ether_dhost, (char *)&ArgusThisMac->phys_union.ether.etherdst, 6); switch (ArgusThisNetworkFlowType) { case ETHERTYPE_PPPOED: case ETHERTYPE_PPPOES: { #define PPPOE_HDRLEN 6 #define PPP_IP 0x0021 const u_char *pppoe; unsigned short ptype; pppoe = ArgusThisUpHdr; ArgusThisUpHdr += PPPOE_HDRLEN; ArgusThisLength -= PPPOE_HDRLEN; ArgusSnapLength -= PPPOE_HDRLEN; ArgusThisPacketPPPoEEncaps++; if (!(pppoe[1])) { if ((ptype = ntohs(*(u_short *)ArgusThisUpHdr)) == PPP_IP) { ArgusThisNetworkFlowType = ETHERTYPE_IP; ArgusThisUpHdr += 2; ArgusThisLength -= 2; ArgusSnapLength -= 2; } } break; } case ETHERTYPE_MPLS_MULTI: case ETHERTYPE_MPLS: { unsigned int label, first = 1; unsigned char exp, bos = 0, ttl; while (!(bos)) { ArgusParseMPLSLabel (ArgusThisUpHdr, &label, &exp, &bos, &ttl); ArgusThisUpHdr += 4; ArgusThisLength -= 4; ArgusSnapLength -= 4; if (first) { first = 0; ArgusThisPacketMPLSLabel = label; } } ArgusThisNetworkFlowType = ArgusDiscoverNetworkProtocol(ArgusThisUpHdr); ArgusThisPacketMPLSEncaps++; break; } case ETHERTYPE_8021Q: { ArgusThisNetworkFlowType = ntohs(*(unsigned short *)(ArgusThisUpHdr + 2)); ArgusThisPacket8021QEncaps = ntohs(*(unsigned short *)(ArgusThisUpHdr)); ArgusThisUpHdr += 4; ArgusThisLength -= 4; ArgusSnapLength -= 4; break; } } if ((proto = (ArgusThisNetworkFlowType & 0xFFFF)) <= ETHERMTU) { /* 802.3 Encapsulation */ struct llc *llc = NULL; unsigned short ether_type = 0; ptr = (unsigned char *) ArgusThisUpHdr; if (ptr[0] == 0x01 && ptr[1] == 0x00 && ptr[2] == 0x0C && ptr[3] == 0x00 && ptr[4] == 0x00) { return (ArgusProcessISL (ep, length)); } llc = (struct llc *) ptr; if (STRUCTCAPTURED(*llc)) { ArgusThisPacketLLCEncaps++; retn = ep; llc = ArgusThisLLC; bcopy((char *) ptr, (char *) llc, sizeof (struct llc)); if (llc->ssap == LLCSAP_GLOBAL && llc->dsap == LLCSAP_GLOBAL) { ArgusProcessIpxHdr (ep, length); return (retn); } if ((((u_char *)ep)[0] == 0xf0) && (((u_char *)ep)[1] == 0xf0)) { ArgusProcessNetbeuiHdr (ep, length); return (retn); } if ((llc->ssap == LLCSAP_ISONS) && (llc->dsap == LLCSAP_ISONS) && (llc->llcui == LLC_UI)) { ArgusProcessIsoclnsHdr((struct ether_header *)ptr, length); return (retn); } if ((llc->ssap == LLCSAP_SNAP) && (llc->dsap == LLCSAP_SNAP)) { if (llc->llcui == LLC_UI) { ((unsigned char *)ðer_type)[0] = ((unsigned char *)&llc->ethertype)[0]; ((unsigned char *)ðer_type)[1] = ((unsigned char *)&llc->ethertype)[1]; ArgusThisNetworkFlowType = ntohs (ether_type); ArgusThisLength -= sizeof(struct llc); ArgusSnapLength -= sizeof(struct llc); ArgusThisUpHdr = (ptr + sizeof(struct llc)); switch (ArgusThisNetworkFlowType) { case ETHERTYPE_8021Q: ArgusThisNetworkFlowType = ntohs(*(unsigned short *)(ArgusThisUpHdr + 2)); ArgusThisPacket8021QEncaps = ntohs(*(unsigned short *)(ArgusThisUpHdr)); ArgusThisUpHdr += 4; ArgusThisLength -= 4; ArgusSnapLength -= 4; } } else { } } else { if ((llc->llcu & LLC_U_FMT) == LLC_U_FMT) { ArgusThisUpHdr += 3; ArgusThisLength -= 3; ArgusSnapLength -= 3; if ((llc->llcu & ~LLC_U_POLL) == LLC_XID) { if (*ArgusThisUpHdr == LLC_XID_FI) { ArgusThisUpHdr += 3; ArgusThisLength -= 3; ArgusSnapLength -= 3; } } } else { ArgusThisUpHdr += 4; ArgusThisLength -= 4; ArgusSnapLength -= 4; } } } } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusProcessEtherHdr(0x%x, %d) returning 0x%x\n", ep, length, retn); #endif return (retn); } extern int ArgusShutDownFlag; int ArgusProcessIpPacket (struct ip *ip, int length, struct timeval *tvp) { int retn = 0; struct ArgusFlowStruct *flow; ArgusThisPacketLLCEncaps = 0; ArgusThisPacketMPLSEncaps = 0; ArgusThisPacket8021QEncaps = 0; ArgusThisPacketPPPoEEncaps = 0; ArgusThisNetworkFlowType = ETHERTYPE_IP; if (!(length) && !(tvp) && !(ip)) ArgusModelerCleanUp (); else { if (ArgusUpdateTime()) ArgusSystemTimeout(); ArgusInterface[ArgusInterfaceIndex].ArgusTotalBytes += length; ArgusThisBytes = length; if (ip) { ArgusInterface[ArgusInterfaceIndex].ArgusTotalPkts++; if (STRUCTCAPTURED(*ip)) { ArgusInterface[ArgusInterfaceIndex].ArgusTotalIPPkts++; if (ArgusCreateIPFlow (ip)) { if ((flow = ArgusFindFlow ()) != NULL) { ArgusUpdateFlow (flow, ARGUS_STATUS); } else { flow = ArgusNewFlow(); } } } } } if ((retn = ArgusWriteOutSocket(ArgusModelerOutputSocket)) < 0) { #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusProcessIpPacket() ArgusWriteOutSocket returned %d\n", retn); ArgusDebug (1, "Shutting Down\n"); #endif ArgusLog (LOG_WARNING, "ArgusProcessIpPacket: ArgusWriteOutSocket Failed to Multiplexor. Shuting Down\n"); ArgusShutDownFlag++; } if (ArgusShutDownFlag) ArgusShutDown(0); #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusProcessIpPacket(0x%x, %d, 0x%x) returning %d\n", ip, length, tvp, retn); #endif return (retn); } int ArgusLogThisPacket = 1; int ArgusProcessPacket (struct ether_header *ep, int length, struct timeval *tvp) { int retn = 0; struct ArgusFlowStruct *flow; ArgusTotalPacket++; if (!(length) && !(tvp) && !(ep)) ArgusModelerCleanUp (); else { if (ArgusUpdateTime()) ArgusSystemTimeout(); if (ep) { ArgusThisIpHdr = NULL; ArgusThisUpHdr = NULL; if (ArgusInterface[ArgusInterfaceIndex].ArgusTotalPkts++ == 0) #ifndef ARGUSPERFMETRICS ArgusStartTime = ArgusGlobalTime; #else gettimeofday (&ArgusStartTime, 0L); #endif ArgusInterface[ArgusInterfaceIndex].ArgusTotalBytes += length; ArgusThisBytes = length; if (STRUCTCAPTURED(*ep)) { if ((ArgusThisEpHdr = ArgusProcessEtherHdr (ep, ArgusThisLength)) != NULL) { if (ArgusCreateFlow (ArgusThisEpHdr, ArgusThisLength)) { if ((flow = ArgusFindFlow ()) != NULL) { ArgusUpdateFlow (flow, ARGUS_STATUS); } else flow = ArgusNewFlow(); } } } } } if ((retn = ArgusWriteOutSocket(ArgusModelerOutputSocket)) < 0) { #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusProcessPacket() ArgusWriteOutSocket returned %d\n", retn); ArgusDebug (1, "Shuting Down\n"); #endif ArgusLog (LOG_WARNING, "ArgusProcessPacket () ArgusWriteOutSocket Failed to Multiplexor. Shuting Down\n"); ArgusShutDownFlag++; } if (ArgusShutDownFlag) ArgusShutDown(0); retn = ArgusLogThisPacket; #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusProcessPacket(0x%x, %d, 0x%x) returning %d\n", ep, length, tvp, retn); #endif return (retn); } int ArgusGenerateStartRecords = 0; struct ArgusFlowStruct * ArgusNewFlow () { struct ArgusFlowStruct *retn = NULL; int ArgusTimeout = 0; ArgusTotalNewFlows++; switch (ArgusThisNetworkFlowType & 0xFFFF) { case ETHERTYPE_IP: if (ArgusThisIpHdr->ip_off & 0x1fff) { retn = ArgusNewFragFlow(); } else { ArgusTimeout = ARGUS_INITIMEOUT; ArgusTotalIPFlows++; } break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: ArgusTimeout = ARGUS_ARPTIMEOUT; default: ArgusTotalNonIPFlows++; ArgusTimeout = ARGUS_OTHERTIMEOUT; break; } if (retn == NULL) { if ((retn = (struct ArgusFlowStruct *) ArgusCalloc (1, sizeof(*retn))) != NULL) { retn->ArgusTimeout = ArgusTimeout; retn->ArgusTransactionNum = ArgusTransactionNum++; retn->state.rev = ArgusThisDir; retn->state.src.idle.min = 0x7FFFFFFF; retn->state.dst.idle.min = 0x7FFFFFFF; retn->state.src.active.min = 0x7FFFFFFF; retn->state.dst.active.min = 0x7FFFFFFF; retn->state.startime = ArgusGlobalTime; retn->state.lasttime = ArgusGlobalTime; retn->qhdr.lasttime = ArgusGlobalTime; retn->qhdr.logtime = ArgusGlobalTime; bcopy((char *) ArgusThisFlow, (char *)&retn->flow, sizeof (*ArgusThisFlow)); retn->ArgusFlowType = ArgusThisNetworkFlowType; if (ArgusThisPacketLLCEncaps) retn->ArgusFlowType |= ARGUS_SNAPENCAPS; if (ArgusThisPacketMPLSEncaps) retn->ArgusFlowType |= ARGUS_MPLS; if (ArgusThisPacket8021QEncaps) retn->ArgusFlowType |= ARGUS_VLAN; if (ArgusThisPacketPPPoEEncaps) retn->ArgusFlowType |= ARGUS_PPPoE; if ((retn->htblhdr = ArgusAddHashEntry (retn)) != NULL) ArgusAddToQueue(ArgusFlowQueue, retn); else ArgusLog (LOG_ERR, "ArgusNewFlow() ArgusAddHashEntry error %s.\n", strerror(errno)); } else ArgusLog (LOG_ERR, "ArgusNewFlow() ArgusCalloc error %s.\n", strerror(errno)); } ArgusUpdateFlow (retn, ARGUS_START); if (ArgusGenerateStartRecords) ArgusSendFlowRecord(retn, ARGUS_START); #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusNewFlow() returning 0x%x\n", retn); #endif return (retn); } void ArgusUpdateFlow (struct ArgusFlowStruct *flowstr, unsigned char state) { int ArgusCurrLength = ArgusThisLength; ArgusTotalUpdates++; ArgusCheckTimeout (flowstr); if (flowstr->state.startime.tv_sec == 0) { flowstr->state.startime = ArgusGlobalTime; flowstr->qhdr.logtime = ArgusGlobalTime; } if (getArgusmflag()) { struct ArgusMacStruct *mac; if ((mac = flowstr->MacDSRBuffer) == NULL) { if ((mac = (struct ArgusMacStruct *) ArgusCalloc (1, sizeof (struct ArgusMacStruct))) != NULL) { if (flowstr->state.rev == ArgusThisDir) { bcopy ((char *) ArgusThisMac, (char *) mac, sizeof (*mac)); } else { mac->type = ArgusThisMac->type; mac->length = ArgusThisMac->length; mac->status = ArgusThisMac->status; bcopy ((char *)&ArgusThisMac->phys_union.ether.ethersrc, (char *)&mac->phys_union.ether.etherdst, sizeof (*mac->phys_union.ether.etherdst)); bcopy ((char *)&ArgusThisMac->phys_union.ether.etherdst, (char *)&mac->phys_union.ether.ethersrc, sizeof (*mac->phys_union.ether.ethersrc)); } flowstr->MacDSRBuffer = (void *) mac; } } else { if (flowstr->state.rev == ArgusThisDir) { if ((bcmp ((char *) ArgusThisMac, (char *) mac, sizeof (*mac)))) { bcopy ((char *) ArgusThisMac, (char *) mac, sizeof (*mac)); flowstr->state.status |= ARGUS_MULTIADDR; } } else { if ((mac->status != ArgusThisMac->status) || (bcmp ((char *)&ArgusThisMac->phys_union.ether.ethersrc, (char *)&mac->phys_union.ether.etherdst, sizeof (*mac->phys_union.ether.etherdst))) || (bcmp ((char *)&ArgusThisMac->phys_union.ether.etherdst, (char *)&mac->phys_union.ether.ethersrc, sizeof (*mac->phys_union.ether.ethersrc)))) { mac->status = ArgusThisMac->status; bcopy ((char *)&ArgusThisMac->phys_union.ether.ethersrc, (char *)&mac->phys_union.ether.etherdst, sizeof (*mac->phys_union.ether.etherdst)); bcopy ((char *)&ArgusThisMac->phys_union.ether.etherdst, (char *)&mac->phys_union.ether.ethersrc, sizeof (*mac->phys_union.ether.ethersrc)); flowstr->state.status |= ARGUS_MULTIADDR; } } } } if (ArgusThisPacketMPLSEncaps) { struct ArgusMplsStruct *mpls = NULL; unsigned int *ArgusThisMpls = NULL; unsigned short ArgusThisStatus, ArgusMplsStatus; unsigned short ArgusChangeStatus; if ((mpls = (struct ArgusMplsStruct *) flowstr->MplsDSRBuffer) == NULL) { if ((mpls = (struct ArgusMplsStruct *) ArgusCalloc (1, sizeof(struct ArgusMplsStruct))) != NULL) { mpls->type = ARGUS_MPLS_DSR; mpls->length = sizeof(mpls); flowstr->MplsDSRBuffer = mpls; } } if (flowstr->state.rev == ArgusThisDir) { ArgusThisMpls = &mpls->slabel; ArgusThisStatus = mpls->status & (ARGUS_SRC_CHANGED | ARGUS_SRC_VLAN); ArgusMplsStatus = ARGUS_SRC_VLAN; ArgusChangeStatus = ARGUS_SRC_CHANGED; } else { ArgusThisMpls = &mpls->dlabel; ArgusThisStatus = mpls->status & (ARGUS_DST_CHANGED | ARGUS_DST_VLAN); ArgusMplsStatus = ARGUS_DST_VLAN; ArgusChangeStatus = ARGUS_DST_CHANGED; } if (mpls->status & ArgusMplsStatus) { if (*ArgusThisMpls != ArgusThisPacketMPLSLabel) { mpls->status |= ArgusChangeStatus; *ArgusThisMpls = ArgusThisPacketMPLSLabel; } } else { mpls->status |= ArgusMplsStatus; *ArgusThisMpls = ArgusThisPacketMPLSLabel; } } if (ArgusThisPacket8021QEncaps) { struct ArgusVlanStruct *vlan = NULL; unsigned short *ArgusThisVlan = NULL; unsigned short ArgusThisStatus, ArgusVlanStatus; unsigned short ArgusChangeStatus; if ((vlan = (struct ArgusVlanStruct *) flowstr->VlanDSRBuffer) == NULL) { if ((vlan = (struct ArgusVlanStruct *) ArgusCalloc (1, sizeof(struct ArgusVlanStruct))) != NULL) { vlan->type = ARGUS_VLAN_DSR; vlan->length = sizeof(*vlan); flowstr->VlanDSRBuffer = vlan; } } if (flowstr->state.rev == ArgusThisDir) { ArgusThisVlan = &vlan->sid; ArgusThisStatus = vlan->status & (ARGUS_SRC_CHANGED | ARGUS_SRC_VLAN); ArgusVlanStatus = ARGUS_SRC_VLAN; ArgusChangeStatus = ARGUS_SRC_CHANGED; } else { ArgusThisVlan = &vlan->did; ArgusThisStatus = vlan->status & (ARGUS_DST_CHANGED | ARGUS_DST_VLAN); ArgusVlanStatus = ARGUS_DST_VLAN; ArgusChangeStatus = ARGUS_DST_CHANGED; } if (vlan->status & ArgusVlanStatus) { if (*ArgusThisVlan != ArgusThisPacket8021QEncaps) { vlan->status |= ArgusChangeStatus; *ArgusThisVlan = ArgusThisPacket8021QEncaps; } } else { vlan->status |= ArgusVlanStatus; *ArgusThisVlan = ArgusThisPacket8021QEncaps; } } if ((ArgusGlobalTime.tv_sec < flowstr->state.startime.tv_sec) || ((ArgusGlobalTime.tv_sec == flowstr->state.startime.tv_sec) && (ArgusGlobalTime.tv_usec < flowstr->state.startime.tv_usec))) { if ((flowstr->state.lasttime.tv_sec < flowstr->state.startime.tv_sec) || ((flowstr->state.lasttime.tv_sec == flowstr->state.startime.tv_sec) && (flowstr->state.lasttime.tv_usec < flowstr->state.startime.tv_usec))) { flowstr->state.lasttime = flowstr->state.startime; } flowstr->state.startime = ArgusGlobalTime; } if ((flowstr->state.lasttime.tv_sec < ArgusGlobalTime.tv_sec) || ((flowstr->state.lasttime.tv_sec == ArgusGlobalTime.tv_sec) && (flowstr->state.lasttime.tv_usec < ArgusGlobalTime.tv_usec))) { flowstr->state.lasttime = ArgusGlobalTime; } if ((flowstr->qhdr.lasttime.tv_sec < flowstr->state.lasttime.tv_sec) || ((flowstr->qhdr.lasttime.tv_sec == flowstr->state.lasttime.tv_sec) && (flowstr->qhdr.lasttime.tv_usec < flowstr->state.lasttime.tv_usec))) { flowstr->qhdr.lasttime = flowstr->state.lasttime; } ArgusUpdateState (flowstr, state); if (ArgusThisIpHdr && ((ArgusThisNetworkFlowType & 0xFFFF) == ETHERTYPE_IP)) { if (((ArgusThisIpHdr->ip_off & 0x1fff) == 0) && (ArgusThisIpHdr->ip_off & IP_MF)) { struct ArgusFlowStruct *frag = NULL; ArgusThisLength = ArgusCurrLength; if (ArgusCreateFRAGFlow (ArgusThisIpHdr)) { struct ArgusFragExtensionBuffer *exbuf; if ((frag = ArgusFindFlow ()) == NULL) { if ((frag = ArgusNewFragFlow ()) == NULL) ArgusLog (LOG_ERR, "ArgusNewFragFlow() returned NULL.\n"); } else { if ((exbuf = (struct ArgusFragExtensionBuffer *) frag->FragDSRBuffer) == NULL) { if ((exbuf = (struct ArgusFragExtensionBuffer *) ArgusCalloc (1, sizeof(*exbuf))) != NULL) { frag->FragDSRBuffer = exbuf; bcopy((char *)ArgusThisFlow, (char *)&exbuf->flow, sizeof(*ArgusThisFlow)); } else ArgusLog (LOG_ERR, "ArgusUpdateFlow: ArgusCalloc returned error %s\n", strerror(errno)); } } exbuf = (struct ArgusFragExtensionBuffer *) frag->FragDSRBuffer; flowstr->state.ofragcnt++; exbuf->flowstr = flowstr; bcopy ((char *)&flowstr->flow, (char *)&exbuf->flow, sizeof (*ArgusThisFlow)); if (frag->state.src.count != 0) exbuf->frag.status |= ARGUS_FRAG_OUT_OF_ORDER; state = ARGUS_STATUS; ArgusTallyStats (frag, state); ArgusUpdateFRAGState (frag, &state); } } } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusUpdateFlow (0x%x, %d) returning\n", flowstr, state); #endif } void ArgusUpdateMACState (struct ArgusFlowStruct *flowstr, unsigned char *state) { } int ArgusUpdateState (struct ArgusFlowStruct *flowstr, unsigned char state) { int retn = 1; struct ArgusFlow *flow; ArgusInProtocol = 1; ArgusUpdateMACState(flowstr, &state); flow = &flowstr->flow; switch (ArgusThisNetworkFlowType & 0xFFFF) { case ETHERTYPE_IP: { if ((flow->ip_flow.ip_p != IPPROTO_ICMP) && (flow->ip_flow.tp_p == ARGUS_FRAG_FLOWTAG)) { ArgusTallyStats (flowstr, state); ArgusUpdateFRAGState (flowstr, &state); } else { switch (flow->ip_flow.ip_p) { case IPPROTO_TCP: ArgusTallyStats (flowstr, state); ArgusUpdateTCPState (flowstr, &state); break; case IPPROTO_UDP: ArgusTallyStats (flowstr, state); ArgusUpdateUDPState (flowstr, &state); break; case IPPROTO_ICMP: ArgusUpdateICMPState (flowstr, &state); break; case IPPROTO_IGMP: { flowstr->ArgusTimeout = ARGUS_IPTIMEOUT; ArgusTallyStats (flowstr, state); ArgusUpdateAppState (flowstr, &state); break; } case IPPROTO_ESP: { ArgusTallyStats (flowstr, state); ArgusUpdateESPState (flowstr, &state); ArgusUpdateAppState (flowstr, &state); break; } default: flowstr->ArgusTimeout = ARGUS_IPTIMEOUT; ArgusTallyStats (flowstr, state); ArgusUpdateAppState (flowstr, &state); break; } } break; } case ETHERTYPE_ARP: case ETHERTYPE_REVARP: ArgusTallyStats (flowstr, state); ArgusUpdateArpState(flowstr, &state); break; default: ArgusTallyStats (flowstr, state); ArgusUpdateAppState(flowstr, &state); break; } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusUpdateState (0x%x, %d) returning %d\n", flowstr, state, retn); #endif return (retn); } #include void ArgusTallyStats (struct ArgusFlowStruct *flow, unsigned char state) { struct ArgusFlowStats *ArgusThisStats; if (flow->state.rev == ArgusThisDir) ArgusThisStats = &flow->state.src; else ArgusThisStats = &flow->state.dst; if (ArgusThisIpHdr) switch (state) { case ARGUS_START: ArgusThisStats->ttl = ArgusThisIpHdr->ip_ttl; ArgusThisStats->tos = ArgusThisIpHdr->ip_tos; ArgusThisStats->ip_id = ArgusThisIpHdr->ip_id; ArgusThisStats->options = ArgusOptionIndicator; break; default: if (ArgusThisStats->ttl != ArgusThisIpHdr->ip_ttl) { ArgusThisStats->status |= ARGUS_TTL_MODIFIED; ArgusThisStats->ttl = ArgusThisIpHdr->ip_ttl; } if (ArgusThisStats->tos != ArgusThisIpHdr->ip_tos) { ArgusThisStats->status |= ARGUS_TOS_MODIFIED; ArgusThisStats->tos = ArgusThisIpHdr->ip_tos; } if (ArgusThisStats->options != ArgusOptionIndicator) { ArgusThisStats->status |= ARGUS_OPTION_MODIFIED; ArgusThisStats->options = ArgusOptionIndicator; } ArgusThisStats->ip_id = ArgusThisIpHdr->ip_id; break; } if (flow->state.startime.tv_sec == 0) { flow->state.startime = ArgusGlobalTime; flow->state.lasttime = ArgusGlobalTime; } ArgusThisStats->count++; ArgusThisStats->bytes += ArgusThisBytes; flow->state.last = ArgusThisStats; #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusTallyStats (0x%x) returning\n", flow); #endif } void ArgusTallyTime (struct ArgusFlowStruct *flow, unsigned char state) { struct ArgusModelerTime *ArgusThisTime; struct ArgusFlowStats *ArgusThisStats; struct timeval *tvp; unsigned long long interval; if (flow->state.rev == ArgusThisDir) ArgusThisStats = &flow->state.src; else ArgusThisStats = &flow->state.dst; if (ArgusInProtocol) ArgusThisTime = &ArgusThisStats->active; else ArgusThisTime = &ArgusThisStats->idle; if ((ArgusThisStats->lasttime.tv_sec < ArgusGlobalTime.tv_sec) || ((ArgusThisStats->lasttime.tv_sec == ArgusGlobalTime.tv_sec) && (ArgusThisStats->lasttime.tv_usec < ArgusGlobalTime.tv_usec))) { if (ArgusThisStats->lasttime.tv_sec > 0) { if ((interval = ArgusAbsTimeDiff (&ArgusGlobalTime, &ArgusThisStats->lasttime)) > 0) { if ((tvp = getArgusFarReportInterval ()) != NULL) { if (interval < ((tvp->tv_sec * 2000000) + tvp->tv_usec)) { if (ArgusThisTime->min > interval) ArgusThisTime->min = interval; if (ArgusThisTime->max < interval) ArgusThisTime->max = interval; ArgusThisTime->sum += interval; ArgusThisTime->sumsqrd += pow (interval, 2.0); ArgusThisTime->n++; } } } } ArgusThisStats->lasttime = ArgusGlobalTime; } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusTallyTime (0x%x) returning\n", flow); #endif } #define ARGUS_MAXRECORDSIZE 2048 u_char ArgusOutputBuffer[ARGUS_MAXRECORDSIZE]; struct ArgusRecord * ArgusGenerateFlowRecord (struct ArgusFlowStruct *flow, unsigned char state) { struct ArgusRecord *argus = (struct ArgusRecord *)ArgusOutputBuffer; struct ArgusFlowStats *src, *dst; struct ArgusRecordHeader *arghdr; bzero ((char *)ArgusOutputBuffer, sizeof(ArgusOutputBuffer)); argus->ahdr.type = ARGUS_FAR; argus->ahdr.cause = state; argus->ahdr.length = sizeof(argus->ahdr); argus->ahdr.seqNumber = ArgusOutputSequence++; argus->ahdr.status = flow->ArgusFlowType; argus->ahdr.argusid = getArgusID(); argus->ahdr.status |= getArgusIDType(); argus->argus_far.type = ARGUS_FAR; argus->argus_far.length = sizeof(argus->argus_far); argus->ahdr.length += sizeof(argus->argus_far); if (flow->state.status & ARGUS_CONNECTED) argus->ahdr.status |= ARGUS_CONNECTED; src = &flow->state.src; dst = &flow->state.dst; switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { if (flow->state.status & ARGUS_ICMPUNREACH_MAPPED) argus->argus_far.status |= ARGUS_ICMPUNREACH_MAPPED; if (flow->state.status & ARGUS_ICMPREDIREC_MAPPED) argus->argus_far.status |= ARGUS_ICMPREDIREC_MAPPED; if (flow->state.status & ARGUS_ICMPTIMXCED_MAPPED) argus->argus_far.status |= ARGUS_ICMPTIMXCED_MAPPED; if (flow->state.src.status & ARGUS_FRAGMENTS) argus->argus_far.attr_ip.soptions |= ARGUS_FRAGMENTS; if (flow->state.src.status & ARGUS_FRAGOVERLAP) argus->argus_far.attr_ip.soptions |= ARGUS_FRAGOVERLAP; if (flow->state.dst.status & ARGUS_FRAGMENTS) argus->argus_far.attr_ip.doptions |= ARGUS_FRAGMENTS; if (flow->state.dst.status & ARGUS_FRAGOVERLAP) argus->argus_far.attr_ip.doptions |= ARGUS_FRAGOVERLAP; if (flow->state.src.status & ARGUS_TTL_MODIFIED) argus->argus_far.attr_ip.soptions |= ARGUS_TTL_MODIFIED; if (flow->state.dst.status & ARGUS_TTL_MODIFIED) argus->argus_far.attr_ip.doptions |= ARGUS_TTL_MODIFIED; if (flow->state.src.status & ARGUS_TOS_MODIFIED) argus->argus_far.attr_ip.soptions |= ARGUS_TOS_MODIFIED; if (flow->state.dst.status & ARGUS_TOS_MODIFIED) argus->argus_far.attr_ip.doptions |= ARGUS_TOS_MODIFIED; if (flow->state.src.status & ARGUS_OPTION_MODIFIED) argus->argus_far.attr_ip.soptions |= ARGUS_OPTION_MODIFIED; if (flow->state.dst.status & ARGUS_OPTION_MODIFIED) argus->argus_far.attr_ip.doptions |= ARGUS_OPTION_MODIFIED; argus->argus_far.attr_ip.soptions |= flow->state.src.options; argus->argus_far.attr_ip.doptions |= flow->state.dst.options; if (flow->flow.ip_flow.ip_p != IPPROTO_ICMP) flow->flow.ip_flow.ip_id = flow->state.src.ip_id; argus->argus_far.attr_ip.sttl = src->ttl; argus->argus_far.attr_ip.stos = src->tos; argus->argus_far.attr_ip.dttl = dst->ttl; argus->argus_far.attr_ip.dtos = dst->tos; break; } case ETHERTYPE_ARP: case ETHERTYPE_REVARP: { struct ArgusARPObject *arpobj; if (flow->NetworkDSRBuffer != NULL) { arpobj = (void *) flow->NetworkDSRBuffer; bcopy (arpobj->respaddr, (unsigned char *)&argus->argus_far.attr_arp.response, 6); } break; } } argus->argus_far.ArgusTransRefNum = flow->ArgusTransactionNum; argus->argus_far.time.start = flow->state.startime; argus->argus_far.time.last = flow->state.lasttime; if (flow->FragDSRBuffer) argus->argus_far.flow = ((struct ArgusFragExtensionBuffer *) flow->FragDSRBuffer)->flow; else argus->argus_far.flow = flow->flow; if (flow->state.rev) { unsigned int tmp; if ((argus->ahdr.status & 0xFFFF) == ETHERTYPE_IP) { tmp = argus->argus_far.flow.ip_flow.ip_src; argus->argus_far.flow.ip_flow.ip_src = argus->argus_far.flow.ip_flow.ip_dst; argus->argus_far.flow.ip_flow.ip_dst = tmp; if ((argus->argus_far.flow.ip_flow.ip_p == IPPROTO_TCP) || (argus->argus_far.flow.ip_flow.ip_p == IPPROTO_UDP)) { tmp = argus->argus_far.flow.ip_flow.sport; argus->argus_far.flow.ip_flow.sport = argus->argus_far.flow.ip_flow.dport; argus->argus_far.flow.ip_flow.dport = tmp; } } } argus->argus_far.src.count = src->count; argus->argus_far.dst.count = dst->count; argus->argus_far.src.bytes = src->bytes; argus->argus_far.dst.bytes = dst->bytes; argus->argus_far.src.appbytes = src->appbytes; argus->argus_far.dst.appbytes = dst->appbytes; switch (argus->ahdr.status & 0xFFFF) { case ETHERTYPE_IP: { switch (argus->argus_far.flow.ip_flow.ip_p) { case IPPROTO_TCP: ArgusTCPFlowRecord (flow, argus, state); break; case IPPROTO_UDP: { ArgusUDPFlowRecord (flow, argus, state); break; } case IPPROTO_ICMP: { ArgusICMPFlowRecord (flow, argus, state); break; } case IPPROTO_IGMP: { break; } case IPPROTO_ESP: { ArgusESPFlowRecord (flow, argus, state); break; } default: { arghdr = NULL; break; } } } case ETHERTYPE_ARP: case ETHERTYPE_REVARP: { break; } default: break; } if (flow->MacDSRBuffer) ArgusMacFlowRecord (flow, argus, state); if (flow->VlanDSRBuffer) ArgusVlanFlowRecord (flow, argus, state); if (flow->MplsDSRBuffer) ArgusMplsFlowRecord (flow, argus, state); if (getArgusGenerateTime()) ArgusTimeFlowRecord (flow, argus, state); if (flow->ICMPDSRBuffer) ArgusICMPMappedFlowRecord (flow, argus, state); if (flow->UserDSRBuffer) ArgusUserDataFlowRecord (flow, argus, state); return (argus); } void ArgusSendFlowRecord (struct ArgusFlowStruct *flow, unsigned char state) { struct ArgusRecord *argus; struct ArgusFlowStats *src, *dst; int retn = 0, len = 0; if (ArgusThisIpHdr) if (((ArgusThisIpHdr->ip_off & 0x1fff) == 0) && (ArgusThisIpHdr->ip_off & IP_MF)) { flow->state.status |= ARGUS_SEND_FRAG_COMPLETE; return; } if (flow->state.src.count || flow->state.dst.count) { ArgusTotalRecords++; if ((argus = ArgusGenerateFlowRecord (flow, state)) != NULL) { len = argus->ahdr.length; #ifdef _LITTLE_ENDIAN ArgusHtoN(argus); #endif if ((retn = ArgusWriteSocket(ArgusModelerOutputSocket, (unsigned char *) argus, len)) < 0) ArgusLog (LOG_ERR, "ArgusSendFlowRecord: ArgusWriteSocket() error %s", strerror(errno)); } if (flow->flow.ip_flow.ip_p != IPPROTO_ICMP) flow->flow.ip_flow.ip_id = 0; flow->state.startime.tv_sec = 0; flow->state.startime.tv_usec = 0; flow->state.lasttime.tv_sec = 0; flow->state.lasttime.tv_usec = 0; src = &flow->state.src; dst = &flow->state.dst; src->count = 0; src->bytes = 0; src->appbytes = 0; dst->count = 0; dst->bytes = 0; dst->appbytes = 0; src->active.n = 0; src->idle.n = 0; src->active.sum = 0; src->idle.sum = 0; src->active.sumsqrd = 0; src->idle.sumsqrd = 0; src->active.max = 0x00000000; src->idle.max = 0x00000000; src->active.min = 0x7FFFFFFF; src->idle.min = 0x7FFFFFFF; dst->active.n = 0; dst->idle.n = 0; dst->active.sum = 0; dst->idle.sum = 0; dst->active.sumsqrd = 0; dst->idle.sumsqrd = 0; dst->active.max = 0x00000000; dst->idle.max = 0x00000000; dst->active.min = 0x7FFFFFFF; dst->idle.min = 0x7FFFFFFF; flow->state.src.status &= ~(ARGUS_FRAGMENTS|ARGUS_FRAGOVERLAP|ARGUS_TOS_MODIFIED|ARGUS_TTL_MODIFIED); flow->state.dst.status &= ~(ARGUS_FRAGMENTS|ARGUS_FRAGOVERLAP|ARGUS_TOS_MODIFIED|ARGUS_TTL_MODIFIED); flow->state.status &= ~(ARGUS_ICMPUNREACH_MAPPED|ARGUS_ICMPREDIREC_MAPPED|ARGUS_ICMPTIMXCED_MAPPED); #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusSendFlowRecord (0x%x, %d) writing record %d wrote %d bytes\n", flow, state, ntohl(argus->ahdr.seqNumber), retn); #endif } flow->qhdr.logtime = ArgusGlobalTime; } void ArgusVlanFlowRecord (struct ArgusFlowStruct *flow, struct ArgusRecord *argus, unsigned char state) { struct ArgusVlanStruct *vlan = NULL; if ((vlan = (struct ArgusVlanStruct *) flow->VlanDSRBuffer) != NULL) { bcopy ((char *)vlan, &((char *)argus)[argus->ahdr.length], sizeof(*vlan)); argus->ahdr.length += sizeof(*vlan); } } void ArgusMplsFlowRecord (struct ArgusFlowStruct *flow, struct ArgusRecord *argus, unsigned char state) { struct ArgusMplsStruct *mpls = NULL; if ((mpls = (struct ArgusMplsStruct *) flow->MplsDSRBuffer) != NULL) { bcopy ((char *)mpls, &((char *)argus)[argus->ahdr.length], sizeof(*mpls)); argus->ahdr.length += sizeof(*mpls); } } void ArgusTimeFlowRecord (struct ArgusFlowStruct *flow, struct ArgusRecord *argus, unsigned char state) { struct ArgusTimeStruct timebuf, *time = &timebuf; bzero ((char *) time, sizeof (*time)); time->type = ARGUS_TIME_DSR; time->length = sizeof (*time); if ((flow->state.src.active.n > 1) || (flow->state.dst.active.n > 1) || (flow->state.src.idle.n > 1) || (flow->state.dst.idle.n > 1)) { if (flow->state.src.active.n > 1) { time->src.act.n = flow->state.src.active.n; time->src.act.min = flow->state.src.active.min; time->src.act.max = flow->state.src.active.max; time->src.act.mean = flow->state.src.active.sum/flow->state.src.active.n; time->src.act.stdev = sqrt (flow->state.src.active.sumsqrd/time->src.act.n - pow (flow->state.src.active.sum/time->src.act.n, 2.0)); } if (flow->state.dst.active.n > 1) { time->dst.act.n = flow->state.dst.active.n; time->dst.act.min = flow->state.dst.active.min; time->dst.act.max = flow->state.dst.active.max; time->dst.act.mean = flow->state.dst.active.sum/flow->state.dst.active.n; time->dst.act.stdev = sqrt (flow->state.dst.active.sumsqrd/time->dst.act.n - pow (flow->state.dst.active.sum/time->dst.act.n, 2.0)); } if (flow->state.src.idle.n > 1) { time->src.idle.n = flow->state.src.idle.n; time->src.idle.min = flow->state.src.idle.min; time->src.idle.max = flow->state.src.idle.max; time->src.idle.mean = flow->state.src.idle.sum/flow->state.src.idle.n; time->src.idle.stdev = sqrt (flow->state.src.idle.sumsqrd/time->src.idle.n - pow (flow->state.src.idle.sum/time->src.idle.n, 2.0)); } if (flow->state.dst.idle.n > 1) { time->dst.idle.n = flow->state.dst.idle.n; time->dst.idle.min = flow->state.dst.idle.min; time->dst.idle.max = flow->state.dst.idle.max; time->dst.idle.mean = flow->state.dst.idle.sum/flow->state.dst.idle.n; time->dst.idle.stdev = sqrt (flow->state.dst.idle.sumsqrd/time->dst.idle.n - pow (flow->state.dst.idle.sum/time->dst.idle.n, 2.0)); } bcopy ((char *)time, &((char *)argus)[argus->ahdr.length], sizeof(*time)); argus->ahdr.length += sizeof(*time); } } void ArgusSystemTimeout () { int retn = 0, recv, drop, i; struct pcap_stat stat; struct timeval *tvp = NULL; if (((ArgusReportTime.tv_sec < ArgusGlobalTime.tv_sec) || ((ArgusReportTime.tv_sec == ArgusGlobalTime.tv_sec) && (ArgusReportTime.tv_usec < ArgusGlobalTime.tv_usec)))) { if (ArgusInputPacketFileType == ARGUSLIBPPKTFILE) { for (i = 0; i < ARGUS_MAXINTERFACE; i++) { if ((ArgusPd[i]) && (pcap_fileno(ArgusPd[i]) >= 0)) { pcap_stats(ArgusPd[i], &stat); recv = stat.ps_recv - ArgusStats[i].ps_recv; drop = stat.ps_drop - ArgusStats[i].ps_drop; ArgusInterface[ArgusInterfaceIndex].ArgusTotalDrop += drop; ArgusStats[i] = stat; } } } ArgusGenerateStatusMar(); #ifdef _LITTLE_ENDIAN ArgusHtoN(ArgusSystemMar); #endif if ((retn = ArgusWriteSocket(ArgusModelerOutputSocket, (unsigned char *) ArgusSystemMar, sizeof(*ArgusSystemMar))) < 0) ArgusLog (LOG_ERR, "ArgusSystemTimeout: ArgusWriteSocket() error %s", strerror(errno)); if ((tvp = getArgusMarReportInterval()) != NULL) { ArgusReportTime.tv_sec = ArgusGlobalTime.tv_sec + tvp->tv_sec; ArgusReportTime.tv_usec += tvp->tv_usec; if (ArgusReportTime.tv_usec > 1000000) { ArgusReportTime.tv_sec++; ArgusReportTime.tv_usec -= 1000000; } } } if (ArgusFlowQueue) ArgusProcessQueue(ArgusFlowQueue, ARGUS_STATUS); #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusSystemTimeout () returning\n"); #endif } void ArgusModelerCleanUp () { ArgusThisIpHdr = NULL; if ((ArgusFlowQueue) && (ArgusFlowQueue->count)) ArgusProcessQueue (ArgusFlowQueue, ARGUS_SHUTDOWN); if (ArgusModelerOutputSocket) { ArgusGenerateClosingMar(ARGUS_SHUTDOWN); #ifdef _LITTLE_ENDIAN ArgusHtoN(ArgusSystemMar); #endif if ((ArgusWriteSocket(ArgusModelerOutputSocket, (unsigned char *) ArgusSystemMar, sizeof(struct ArgusRecord))) < 0) ArgusLog (LOG_ERR, "ArgusModelerCleanUp: ArgusWriteSocket() error %s", strerror(errno)); while (!(ArgusListEmpty(ArgusModelerOutputSocket->ArgusOutputList))) if (ArgusWriteOutSocket(ArgusModelerOutputSocket) < 0) break; } #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusModelerCleanUp () returning\n"); #endif } int ArgusCreateFlow (struct ether_header *ep, int length) { int retn = 0; ArgusThisDir = 0; bzero ((char *)ArgusThisFlow, sizeof(*ArgusThisFlow)); ArgusThisHash = 0; ArgusThisIpHdr = NULL; switch (ArgusThisNetworkFlowType & 0xFFFF) { case ETHERTYPE_IP: { struct ip *ip = (struct ip *) ArgusThisUpHdr; if (STRUCTCAPTURED(*ip)) { #if defined(LBL_ALIGN) if ((long) ip & (sizeof (long) - 1)) { bcopy ((unsigned char *) ip, (unsigned char *) ArgusAlignBuf, ArgusSnapLength); ip = (struct ip *) ArgusAlignBuf; ArgusThisSnapEnd = ArgusAlignBuf + ArgusSnapLength; } #endif ArgusInterface[ArgusInterfaceIndex].ArgusTotalIPPkts++; retn = ArgusCreateIPFlow (ip); } break; } case ETHERTYPE_ARP: case ETHERTYPE_REVARP: { ArgusInterface[ArgusInterfaceIndex].ArgusTotalNonIPPkts++; ArgusThisLength = length; retn = ArgusCreateArpFlow ((struct ether_arp *)ArgusThisUpHdr); break; } default: { int dstgteq = 1, i; ArgusInterface[ArgusInterfaceIndex].ArgusTotalNonIPPkts++; ArgusThisLength = length; bzero ((unsigned char *) ArgusThisFlow, sizeof(*ArgusThisFlow)); #ifndef ETH_ALEN #define ETH_ALEN 6 #endif for (i = 0; i < ETH_ALEN; i++) { if (((unsigned char *)&ep->ether_shost)[i] != ((unsigned char *)&ep->ether_dhost)[i]) { if (((unsigned char *)&ep->ether_shost)[i] > ((unsigned char *)&ep->ether_dhost)[i]) dstgteq = 0; break; } } if (dstgteq) { ArgusThisDir = 0; bcopy ((char *) ep, (char *)&ArgusThisFlow->mac_flow.ehdr, sizeof (struct ether_header)); } else { ArgusThisDir = 1; bcopy ((char *)&ep->ether_shost, (char *)&ArgusThisFlow->mac_flow.ehdr.ether_dhost, ETH_ALEN); bcopy ((char *)&ep->ether_dhost, (char *)&ArgusThisFlow->mac_flow.ehdr.ether_shost, ETH_ALEN); ArgusThisFlow->mac_flow.ehdr.ether_type = ep->ether_type; } if (ArgusThisPacketLLCEncaps) { ArgusThisFlow->mac_flow.ehdr.ether_type = 0; switch (ArgusThisNetworkFlowType & 0xFFFF) { case ARGUS_CLNS: case ARGUS_ESIS: case ARGUS_ISIS: case ARGUS_NULLNS: break; default: ArgusThisNetworkFlowType &= ~(0xFFFF); break; } if (dstgteq) { ArgusThisFlow->mac_flow.ssap = ArgusThisLLC->ssap; ArgusThisFlow->mac_flow.dsap = ArgusThisLLC->dsap; } else { ArgusThisFlow->mac_flow.ssap = ArgusThisLLC->dsap; ArgusThisFlow->mac_flow.dsap = ArgusThisLLC->ssap; } } retn = 1; } break; } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusCreateFlow (0x%x, %d) returning %d\n", ep, length, retn); #endif return (retn); } #include static struct ArgusFlow ThisFlow; int ArgusCreateIPFlow (struct ip *ip) { int retn = 0; char *nxtHdr = (char *)((char *)ip + (ip->ip_hl << 2)); arg_uint32 saddr, daddr; arg_uint16 sport = 0, dport = 0, ip_id = 0; arg_uint8 proto, tp_p = 0; arg_uint32 len; int hlen, ArgusOptionLen; if (STRUCTCAPTURED(*ip)) { #if defined(LBL_ALIGN) if ((long) ip & (sizeof (long) - 1)) { bcopy ((unsigned char *) ip, (unsigned char *) ArgusAlignBuf, ArgusSnapLength); ip = (struct ip *) ArgusAlignBuf; ArgusThisSnapEnd = ArgusAlignBuf + ArgusSnapLength; } #endif bzero ((char *)ArgusThisFlow, sizeof(*ArgusThisFlow)); ArgusThisHash = 0; ArgusThisIpHdr = ip; #ifdef _LITTLE_ENDIAN ip->ip_len = ntohs(ip->ip_len); ip->ip_id = ntohs(ip->ip_id); ip->ip_off = ntohs(ip->ip_off); ip->ip_src.s_addr = ntohl(ip->ip_src.s_addr); ip->ip_dst.s_addr = ntohl(ip->ip_dst.s_addr); #endif hlen = ip->ip_hl << 2; if ((len = (ip->ip_len - hlen)) >= 0) { if ((ArgusIPPacketLenOff = (ip->ip_len - ArgusThisLength)) < 0) ArgusThisBytes += ArgusIPPacketLenOff; ArgusOptionIndicator = '\0'; if ((ArgusOptionLen = (hlen - sizeof (struct ip))) > 0) ArgusOptionIndicator = ArgusParseIPOptions ((unsigned char *) (ip + 1), ArgusOptionLen); ArgusThisLength = len; ArgusSnapLength -= hlen; ArgusThisDir = 0; saddr = ip->ip_src.s_addr; daddr = ip->ip_dst.s_addr; proto = ip->ip_p; if ((ip->ip_off & 0x1fff) == 0) { if (proto == IPPROTO_AH) { struct AHHeader *ah = (struct AHHeader *) nxtHdr; proto = ah->nxt; nxtHdr = (char *)(ah + 1); } ArgusThisUpHdr = (unsigned char *)nxtHdr; switch (proto) { case IPPROTO_ESP: retn = ArgusCreateESPFlow (ip); return (retn); case IPPROTO_ICMP: retn = ArgusCreateICMPFlow (ip); return (retn); case IPPROTO_TCP: { if (len >= sizeof (struct tcphdr)) { struct tcphdr *tp = (struct tcphdr *) nxtHdr; sport = ntohs(tp->th_sport); dport = ntohs(tp->th_dport); } break; } case IPPROTO_UDP: { if (len >= sizeof (struct udphdr)) { struct udphdr *up = (struct udphdr *) nxtHdr; sport = ntohs(up->uh_sport); dport = ntohs(up->uh_dport); } break; } case IPPROTO_IGMP: { if (len >= sizeof (struct igmp)) { struct igmp *igmp = (struct igmp *) nxtHdr; sport = igmp->igmp_type; } break; } default: break; } } else { ArgusThisDir = 0; ip_id = ip->ip_id; tp_p = ARGUS_FRAG_FLOWTAG; sport = 0xFFFF; dport = 0xFFFF; } ThisFlow.ip_flow.ip_src = saddr; ThisFlow.ip_flow.ip_dst = daddr; ThisFlow.ip_flow.ip_p = proto; ThisFlow.ip_flow.sport = sport; ThisFlow.ip_flow.dport = dport; ThisFlow.ip_flow.ip_id = ip_id; ThisFlow.ip_flow.tp_p = tp_p; switch (proto) { default: case IPPROTO_TCP: case IPPROTO_UDP: if ((ThisFlow.ip_flow.tp_p != ARGUS_FRAG_FLOWTAG) && (dport > sport || ((sport == dport) && (saddr < daddr)))) { ThisFlow.ip_flow.ip_src = daddr; ThisFlow.ip_flow.ip_dst = saddr; ThisFlow.ip_flow.sport = dport; ThisFlow.ip_flow.dport = sport; ArgusThisDir = 1; } if (ThisFlow.ip_flow.dport == IPPORT_BOOTPS) { struct udphdr *udp = (struct udphdr *) ArgusThisUpHdr; struct bootp *bp = (struct bootp *) (udp + 1); if (BYTESCAPTURED(*bp, 8)) { ThisFlow.ip_flow.ip_src = ntohl(bp->bp_xid); ThisFlow.ip_flow.ip_dst = 0; } } break; case IPPROTO_ICMP: if (ArgusThisDir && (ThisFlow.ip_flow.tp_p != ARGUS_FRAG_FLOWTAG)) { ThisFlow.ip_flow.ip_src = daddr; ThisFlow.ip_flow.ip_dst = saddr; } break; } bcopy ((unsigned char *)&ThisFlow, (unsigned char *) ArgusThisFlow, sizeof(*ArgusThisFlow)); retn = 1; } } #ifdef ARGUSDEBUG ArgusDebug (7, "ArgusCreateIPFlow (0x%x) returning %d\n", ip, retn); #endif return (retn); } void ArgusTimeOut(struct ArgusFlowStruct *flow) { int generateFlowRecord = 1; if (flow->FragDSRBuffer != NULL) { if (ArgusUpdateParentFlow (flow)) { generateFlowRecord = 0; } } if (generateFlowRecord) ArgusSendFlowRecord(flow, ARGUS_TIMEOUT); ArgusDeleteObject (flow); #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusTimeOut (0x%x) returning\n", flow); #endif } unsigned short ArgusParseIPOptions (unsigned char *ptr, int len) { unsigned short retn = 0; int offset = 0; for (; len > 0; ptr += offset, len -= offset) { switch (*ptr) { case IPOPT_EOL: break; case IPOPT_NOP: break; case IPOPT_TS: retn |= ARGUS_TIMESTAMP; break; case IPOPT_RR: retn |= ARGUS_RECORDROUTE; break; case IPOPT_SECURITY: retn |= ARGUS_SECURITY; break; case IPOPT_LSRR: retn |= ARGUS_LSRCROUTE; break; case IPOPT_SSRR: retn |= ARGUS_SSRCROUTE; break; case IPOPT_SATID: retn |= ARGUS_SATNETID; break; default: retn |= ARGUS_RECORDROUTE; break; } if ((*ptr == IPOPT_EOL) || (*ptr == IPOPT_NOP)) offset = 1; else { offset = ptr[1]; if (!(offset && (offset <= len))) break; } } return (retn); } int getArgusmflag () { return(Argusmflag); } void setArgusmflag (int value) { Argusmflag = value; } int getArgusGenerateTime() { return (ArgusGenerateTime); } void setArgusGenerateTime(int value) { ArgusGenerateTime = value; } int getArgusUserDataLen () { return (ArgusUserDataLen); } void setArgusUserDataLen (int value) { ArgusUserDataLen = value; setArgusSnapLen (value + ARGUS_MINSNAPLEN); } int getArgusSnapLen() { return (ArgusSnapLen); } void setArgusSnapLen(int value) { ArgusSnapLen = value; } int getArgusMajorVersion(void) { return (ArgusMajorVersion); } void setArgusMajorVersion(int value) { ArgusMajorVersion = value; } int getArgusMinorVersion(void) { return (ArgusMinorVersion); } void setArgusMinorVersion(int value) { if (ArgusMinorVersion != value) { ArgusMinorVersion = value; } } unsigned char getArgusInterfaceType(void) { return (ArgusInterfaceType); } void setArgusInterfaceType(unsigned char value) { ArgusInterfaceType = value; } unsigned char getArgusInterfaceStatus(void) { return (ArgusInterfaceStatus); } void setArgusInterfaceStatus(unsigned char value) { ArgusInterfaceStatus = value; } struct timeval * getArgusFarReportInterval(void) { return (&ArgusFarReportInterval); } unsigned int getArgusLocalNet(void) { return (ArgusLocalNet); } unsigned int getArgusNetMask(void) { return (ArgusNetMask); } void setArgusLocalNet(unsigned int value) { ArgusLocalNet = value; } unsigned int getArgusID(void) { return (ArgusID); } void setArgusID(unsigned int value) { ArgusID = value; } unsigned int getArgusIDType(void) { return (ArgusIDType); } void setArgusIDType(unsigned int value) { ArgusIDType = value; } int getArgusResponseStatus(void) { return (ArgusResponseStatus); } void setArgusResponseStatus(int value) { ArgusResponseStatus = value; } int getArgusIPTimeout(void) { return (ArgusIPTimeout); } int getArgusTCPTimeout(void) { return (ArgusTCPTimeout); } int getArgusICMPTimeout(void) { return (ArgusICMPTimeout); } int getArgusIGMPTimeout(void) { return (ArgusIGMPTimeout); } int getArgusFRAGTimeout(void) { return (ArgusFRAGTimeout); } #include #include void setArgusFarReportInterval (char *value) { struct timeval *tvp = getArgusFarReportInterval(); struct timeval ovalue; double thisvalue = 0.0, iptr, fptr; int ivalue = 0; char *ptr = NULL;; if (tvp != NULL) { ovalue = *tvp; tvp->tv_sec = 0; tvp->tv_usec = 0; } else { ovalue.tv_sec = 0; ovalue.tv_usec = 0; } if (((ptr = strchr (value, '.')) != NULL) || isdigit((int)*value)) { if (ptr != NULL) { thisvalue = atof(value); } else { if (isdigit((int)*value)) { ivalue = atoi(value); thisvalue = ivalue * 1.0; } } fptr = modf(thisvalue, &iptr); tvp->tv_sec = iptr; tvp->tv_usec = fptr * 1000000; if ((ovalue.tv_sec > tvp->tv_sec) || ((ovalue.tv_sec == tvp->tv_sec) && (ovalue.tv_usec > tvp->tv_usec))) ArgusSystemTimeout(); } else *tvp = ovalue; } void setArgusTCPTimeout(int value) { ArgusTCPTimeout = value; } void setArgusIPTimeout(int value) { ArgusIPTimeout = value; } void setArgusICMPTimeout(int value) { ArgusICMPTimeout = value; } void setArgusIGMPTimeout(int value) { ArgusICMPTimeout = value; } void setArgusFRAGTimeout(int value) { ArgusFRAGTimeout = value; } int getArgusAflag () { return (ArgusAflag); } void setArgusAflag(int value) { ArgusAflag = value; } int getArgusdflag(void) { return (Argusdflag); } void setArgusdflag(int value) { if (Argusdflag && !(value)) { } if (value) { } Argusdflag = value; } void setArgusLink(unsigned int value) { ArgusLink = value; } void setArgusNetMask(unsigned int value) { ArgusNetMask = value; }