/* 1900, Sat 7 Jul 01 (NZT) MET_VARS.C: AU Internet Accounting Meter snmp agent Based on the CMU snmpd version, snmpd.c Copyright (C) 1992-2002 by Nevil Brownlee, CAIDA | University of Auckland */ /* * $Log: met_vars.c,v $ * Revision 1.1.1.2.2.12 2002/02/23 01:57:30 nevil * Moving srl examples to examples/ directory. Modified examples/Makefile.in * * Revision 1.1.1.2.2.10 2001/05/24 02:19:54 nevil * LfapMet implemented by Remco Poortinga. * MinPDUs implemented by Nevil. * * Revision 1.1.1.2.2.7 2000/10/26 23:24:09 nevil * Write log_msg messages to meter.log file * * Revision 1.1.1.2.2.6 2000/08/08 19:44:52 nevil * 44b8 release * * Revision 1.1.1.2.2.4 2000/06/06 03:38:20 nevil * Combine NEW_ATR with TCP_ATR, various bug fixes * * Revision 1.1.1.2.2.1 2000/01/12 02:57:10 nevil * Implement 'packet pair matched' turnaroundtime distribution attributes. * Fix ASN-related bugs in NeTraMet, distribution-related bugs in fd_filter. * * Revision 1.1.1.2 1999/10/03 21:06:24 nevil * *** empty log message *** * * Revision 1.1.1.1.2.14 1999/09/24 04:09:47 nevil * *** empty log message *** * * Revision 1.1.1.1.2.13 1999/09/24 02:58:40 nevil * Polish up code to get rid of warning messages from Borland (DOS) compiler. * Make manager PeerAddress buffers NSAP_ADDR_LEN bytes long. * Add asn_lookup variable - only call FindSubnet if ruleset uses ASNs. * * Revision 1.1.1.1.2.12 1999/09/22 05:38:42 nevil * Improve code to work properly on 64-bit machines * - Add OS=ALPHA handling to configure.in * - Clean up the Alpha compiler warnings * - Change all the snmp-related code to use Bit32 instead of unsigned long * * Revision 1.1.1.1.2.11 1999/09/14 00:45:28 nevil * 4.3 Release .. * - Implement -D option to run NeTraMet as a daemon * - Tidy up the on-line help displays * * Revision 1.1.1.1.2.10 1999/05/26 02:41:40 nevil * Integrate V6 and ASN code into PC versions of the meter. * This required a rework of the makefiles, using @cflags.opt files * to provide a much longer command line to the Borland C compiler. * * Revision 1.1.1.1.2.9 1999/05/17 00:11:57 nevil * Fixed 'reuse of ruleset row' problem: * When a ruleset row is destroyed, set_RowStatus calls free_rulespace() * and recover_flows(). free_rulespace() zeroed its varibales in the * ri[] row, but recover_flows() didn't (it should have zeroed * ri_flow_chain). This left ri_flow_chain pointing to a free flow, * which cause problems if a manager tried to reuse this row for a * new ruleset. Fixed by zeroing all of the ri[] row. (Also commented * out the zeroing code from free_rulesace). * * Revision 1.1.1.1.2.8 1999/04/13 05:13:34 nevil * Use log_msg for ALL error messages * * Revision 1.1.1.1.2.7 1999/02/15 21:24:08 nevil * Distribution file for 4.3b9 * * Revision 1.1.1.1.2.5 1999/01/20 03:55:50 nevil * Implementation of TCP attributes, part 4 * * Revision 1.1.1.1.2.4 1999/01/08 01:31:54 nevil * Implementation of TCP attributes, part 3 * * Revision 1.1.1.1.2.3 1998/12/22 23:53:09 nevil * Implementation of TCP attributes, part 2 * * Revision 1.1.1.1 1998/11/16 03:57:29 nevil * Import of NeTraMet 4.3b3 * * Revision 1.1.1.1 1998/11/16 03:22:01 nevil * Import of release 4.3b3 * * Revision 1.1.1.1.2.1 1998/11/11 23:14:45 nevil * Only include malloc.h if we HAVE_MALLOC_H * * Revision 1.1.1.1 1998/10/28 20:31:27 nevil * Import of NeTraMet 4.3b1 * * Revision 1.1.3.1.2.2 1998/10/19 22:32:46 nevil * Meter improvements, mostly arising from developments for the * OCxMON meter. These are documented in notes_oc.txt * * Revision 1.1.3.1.2.1 1998/10/18 20:51:20 nevil * Added Nicolai's patches, some 'tidying up' of the source * * Revision 1.2 1998/05/22 03:57:35 rtfm * Implement better hashing algorithm for flow and rule tables */ #if HAVE_CONFIG_H #include #endif #define noTESTING #define noPKTESTING #define noRTTESTING #define noPSTESTING #define noGC_TEST #define noH_TEST #define DST_TESTING 0 #define TCP_TESTING 0 #define STR_DIST_DEBUG 1 /* Debug: why do stream distribs stop updating? */ #include #include #include #include #include #include #include #include #include "ausnmp.h" #if defined(DOS) #include #include #include "..\wattcp\tcp.h" #else #if HAVE_MALLOC_H # include #endif #include #include #endif #include "asn1.h" /* CMU snmp include files */ #include "snmp.h" #include "snmpimpl.h" #include "mib.h" #if defined(DOS) && !OCX_NTM && !OC3_NTM #include "..\wattcp\pktdrv.h" #endif #include "pktsnap.h" #include "flowhash.h" #include "met_vars.h" /* Constants for snmp oids */ extern Bit32 rsc_n_searches, /* In flowhash.c */ rsc_mx_range, rsc_av_range, /* Flow index range searched */ rsc_mx_tests, rsc_av_tests; /* Nbr of TimeFilter tests */ #ifdef DEBUG void paddr(Bit8 huge *a); void daddr(Bit8 huge *a); void pkey(char *msg, struct flow huge *n); #endif Bit32 retval; #if !defined(DOS) char syslog_name[256] = ""; FILE *log_file = NULL; /* Local log file for Unix hosts */ char *logname = "meter.log"; #endif void init_snmp(void) { #if defined(LOG_LOCAL) && !defined(DOS) if (*syslog_name) openlog(syslog_name, LOG_PID, LOG_LOCAL); #endif } #define flowMIB 1, 3, 6, 1, 2, 1, 40 #define U_AUCKLAND 1, 3, 6, 1, 4, 1, 411 char version_descr[] = #if OCX_NTM || OC3_NTM "OCxMON: NeTraMet Meter " #elif NF_CISCO_DATA # if defined(__FLAT__) "NetFlowMet: 32-bit Meter " # else "NetFlowMet: Network Meter " # endif #elif CR_DATA "NeTraMet: CoralReef Meter " #elif DAG_DATA "NeTraMet: Dag Meter " #elif defined(__FLAT__) "NeTraMet: 32-bit Meter " #elif defined(DOS) "NeTraMet: 16-bit Meter " #else "NeTraMet: Network Meter " #endif ver_str; oid version_id[] = {U_AUCKLAND, 1, ver_maj,ver_min, 0}; /* NeTraMet maj.min */ extern char interface_name[]; /* Device name for metered interface */ int bad_uptimes = 0; /* For uptime debugging */ unsigned long pc_noflowpkts = 0; /* New Algorithm for SNMPv2C: Variables now appear in the table below without trailing zeroes or subscript markers (MAX_SUBID), and the lengths in the table no longer include those trailers. Each var_* routine must know the proper length of all its variables and act accordingly */ #define RSX 255 /* Rule Set Index */ #define IFX 255 /* Interface table index */ #define CTX 255 /* Collector table index */ #define MTX 255 /* Manager table index */ #define FTX 255 /* Flow table index */ #define TMX 255 /* Time index (first or last time) */ #define ANX 255 /* Attribute number index */ #define PSS 255 /* Package selector string */ #define RNX 255 /* Rule number index */ struct variable variables[] = { /* these must be lexicographly ordered by the name field */ {{MIB, 1, 1}, 8, STRING, VERSION_DESCR, RONLY, var_system}, {{MIB, 1, 2}, 8, OBJID, VERSION_ID, RONLY, var_system}, {{MIB, 1, 3}, 8, TIMETICKS, UPTIME, RONLY, var_system}, {{MIB, 2, 1}, 8, INTEGER, IFNUMBER, RONLY, var_system}, /* {{flowMIB, 1, 1, 1, 1, RSX }, 11, INTEGER, RIINDEX, NOACCESS,var_rinfo}, */ {{flowMIB, 1, 1, 1, 2/*,RSX*/}, 11, INTEGER, RIRULESIZE, RWRITE, var_rinfo}, {{flowMIB, 1, 1, 1, 3/*,RSX*/}, 11, STRING, RIOWNER, RWRITE, var_rinfo}, {{flowMIB, 1, 1, 1, 4/*,RSX*/}, 11, TIMETICKS, RITIMESTAMP, RONLY, var_rinfo}, {{flowMIB, 1, 1, 1, 5/*,RSX*/}, 11, INTEGER, RISTATUS, RWRITE, var_rinfo}, {{flowMIB, 1, 1, 1, 6/*,RSX*/}, 11, STRING, RINAME, RWRITE, var_rinfo}, /* {{flowMIB, 1, 1, 1, 7, RSX }, 11, INTEGER, RIRULESREADY, RWRITE, var_rinfo}, */ {{flowMIB, 1, 1, 1, 8/*,RSX*/}, 11, INTEGER, RIFLOWCOUNT, RONLY, var_rinfo}, {{flowMIB, 1, 2, 1, 1/*,IFX*/}, 11, INTEGER, IFACE_RATE, RWRITE, var_rinfo}, {{flowMIB, 1, 2, 1, 2/*,IFX*/}, 11, COUNTER, IFACE_LOST, RONLY, var_rinfo}, /* {{flowMIB, 1, 3, 1, 1, CTX }, 11, INTEGER, CIINDEX, NOACCESS, var_rinfo}, */ {{flowMIB, 1, 3, 1, 2/*,CTX*/}, 11, INTEGER, CITIMEOUT, RWRITE, var_rinfo}, {{flowMIB, 1, 3, 1, 3/*,CTX*/}, 11, STRING, CIOWNER, RWRITE, var_rinfo}, {{flowMIB, 1, 3, 1, 4/*,CTX*/}, 11, TIMETICKS, CILASTTIME, RWRITE, var_rinfo}, {{flowMIB, 1, 3, 1, 5/*,CTX*/}, 11, TIMETICKS, CIPREVTIME, RONLY, var_rinfo}, {{flowMIB, 1, 3, 1, 6/*,CTX*/}, 11, INTEGER, CISTATUS, RWRITE, var_rinfo}, {{flowMIB, 1, 3, 1, 7/*,CTX*/}, 11, INTEGER, CIRULESET, RWRITE, var_rinfo}, {{flowMIB, 1, 3, 1, 8/*,CTX*/}, 11, INTEGER, CIMINPDUS, RWRITE, var_rinfo}, {{flowMIB, 1, 3, 1, 9/*,CTX*/}, 11, INTEGER, CITIMEMARK, RWRITE, var_rinfo}, /* {{flowMIB, 1, 4, 1, 1, MTX }, 11, INTEGER, MIINDEX, NOACCESS, var_rinfo}, */ {{flowMIB, 1, 4, 1, 2/*,MTX*/}, 11, INTEGER, MICURRENTRULESET, RWRITE, var_rinfo}, {{flowMIB, 1, 4, 1, 3/*,MTX*/}, 11, INTEGER, MISTANDBYRULESET, RWRITE, var_rinfo}, {{flowMIB, 1, 4, 1, 4/*,MTX*/}, 11, INTEGER, MIHIGHWATERMARK, RWRITE, var_rinfo}, /* {{flowMIB, 1, 4, 1, 5 ,MTX }, 11, INTEGER, MICOUNTERWRAP, RWRITE, var_rinfo}, */ {{flowMIB, 1, 4, 1, 6/*,MTX*/}, 11, STRING, MIOWNER, RWRITE, var_rinfo}, {{flowMIB, 1, 4, 1, 7/*,MTX*/}, 11, TIMETICKS, MITIMESTAMP, RONLY, var_rinfo}, {{flowMIB, 1, 4, 1, 8/*,MTX*/}, 11, INTEGER, MISTATUS, RWRITE, var_rinfo}, {{flowMIB, 1, 4, 1, 9/*,MTX*/}, 11, INTEGER, MIRUNNINGSTANDBY, RWRITE, var_rinfo}, {{flowMIB, 1, 5}, 9, INTEGER, FLOODMARK, RWRITE, var_system}, {{flowMIB, 1, 6}, 9, INTEGER, INACT_TIMEOUT, RWRITE, var_system}, {{flowMIB, 1, 7}, 9, INTEGER, ACTIVE_FLOWS, RWRITE, var_system}, {{flowMIB, 1, 8}, 9, INTEGER, MAX_FLOWS, RWRITE, var_system}, {{flowMIB, 1, 9}, 9, INTEGER, FLOOD_MODE, RWRITE, var_system}, /* {{flowMIB, 2, 1, 1, 1, RSX,TMX,FTX }, 11,INTEGER, FTFLOWINDEX, NOACCESS, var_ft}, */ /* {{flowMIB, 2, 1, 1, 2, RSX,TMX,FTX }, 11,TIMETICKS, FTFLOWTIMEMARK, NOACCESS, var_ft}, */ {{flowMIB, 2, 1, 1, 3/*,RSX,TMX,FTX*/}, 11,INTEGER, FTFLOWSTATUS, RONLY, var_ft}, {{flowMIB, 2, 1, 1, 4/*,RSX,TMX,FTX*/}, 11,INTEGER, FTLOWINTERFACE, RONLY, var_ft}, {{flowMIB, 2, 1, 1, 5/*,RSX,TMX,FTX*/}, 11,INTEGER, FTLOWADJACENTTYPE, RONLY, var_ft}, {{flowMIB, 2, 1, 1, 6/*,RSX,TMX,FTX*/}, 11,STRING, FTLOWADJACENTADDRESS, RONLY, var_ft}, {{flowMIB, 2, 1, 1, 7/*,RSX,TMX,FTX*/}, 11,STRING, FTLOWADJACENTMASK, RONLY, var_ft}, {{flowMIB, 2, 1, 1, 8/*,RSX,TMX,FTX*/}, 11,INTEGER, FTLOWPEERTYPE, RONLY, var_ft}, {{flowMIB, 2, 1, 1, 9/*,RSX,TMX,FTX*/}, 11,STRING, FTLOWPEERADDRESS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,10/*,RSX,TMX,FTX*/}, 11,STRING, FTLOWPEERMASK, RONLY, var_ft}, {{flowMIB, 2, 1, 1,11/*,RSX,TMX,FTX*/}, 11,INTEGER, FTLOWTRANSTYPE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,12/*,RSX,TMX,FTX*/}, 11,STRING, FTLOWTRANSADDRESS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,13/*,RSX,TMX,FTX*/}, 11,STRING, FTLOWTRANSMASK, RONLY, var_ft}, {{flowMIB, 2, 1, 1,14/*,RSX,TMX,FTX*/}, 11,INTEGER, FTHIINTERFACE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,15/*,RSX,TMX,FTX*/}, 11,INTEGER, FTHIADJACENTTYPE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,16/*,RSX,TMX,FTX*/}, 11,STRING, FTHIADJACENTADDRESS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,17/*,RSX,TMX,FTX*/}, 11,STRING, FTHIADJACENTMASK, RONLY, var_ft}, {{flowMIB, 2, 1, 1,18/*,RSX,TMX,FTX*/}, 11,INTEGER, FTHIPEERTYPE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,19/*,RSX,TMX,FTX*/}, 11,STRING, FTHIPEERADDRESS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,20/*,RSX,TMX,FTX*/}, 11,STRING, FTHIPEERMASK, RONLY, var_ft}, {{flowMIB, 2, 1, 1,21/*,RSX,TMX,FTX*/}, 11,INTEGER, FTHITRANSTYPE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,22/*,RSX,TMX,FTX*/}, 11,STRING, FTHITRANSADDRESS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,23/*,RSX,TMX,FTX*/}, 11,STRING, FTHITRANSMASK, RONLY, var_ft}, {{flowMIB, 2, 1, 1,24/*,RSX,TMX,FTX*/}, 11,INTEGER, FTPDUSCALE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,25/*,RSX,TMX,FTX*/}, 11,INTEGER, FTOCTETSCALE, RONLY, var_ft}, /* {{flowMIB, 2, 1, 1,26, RSX,TMX,FTX }, 11,INTEGER, FTRULESET, NOACCESS, var_ft}, */ {{flowMIB, 2, 1, 1,27/*,RSX,TMX,FTX*/}, 11,COUNTER64, FTUPOCTETS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,28/*,RSX,TMX,FTX*/}, 11,COUNTER64, FTUPPDUS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,29/*,RSX,TMX,FTX*/}, 11,COUNTER64, FTDOWNOCTETS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,30/*,RSX,TMX,FTX*/}, 11,COUNTER64, FTDOWNPDUS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,31/*,RSX,TMX,FTX*/}, 11,TIMETICKS, FTFIRSTTIME, RONLY, var_ft}, {{flowMIB, 2, 1, 1,32/*,RSX,TMX,FTX*/}, 11,TIMETICKS, FTLASTTIME, RONLY, var_ft}, {{flowMIB, 2, 1, 1,36/*,RSX,TMX,FTX*/}, 11,INTEGER, FTSOURCECLASS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,37/*,RSX,TMX,FTX*/}, 11,INTEGER, FTDESTCLASS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,38/*,RSX,TMX,FTX*/}, 11,INTEGER, FTFLOWCLASS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,39/*,RSX,TMX,FTX*/}, 11,INTEGER, FTSOURCEKIND, RONLY, var_ft}, {{flowMIB, 2, 1, 1,40/*,RSX,TMX,FTX*/}, 11,INTEGER, FTDESTKIND, RONLY, var_ft}, {{flowMIB, 2, 1, 1,41/*,RSX,TMX,FTX*/}, 11,INTEGER, FTFLOWKIND, RONLY, var_ft}, #if NEW_ATR {{flowMIB, 2, 1, 1,65/*,RSX,TMX,FTX*/}, 11,UINTEGER, FTDISTRIBUTIONS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,66/*,RSX,TMX,FTX*/}, 11,STRING, FTTOPACKETSIZE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,67/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMPACKETSIZE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,68/*,RSX,TMX,FTX*/}, 11,STRING, FTTOINTERARRIVALTIME, RONLY, var_ft}, {{flowMIB, 2, 1, 1,69/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMINTERARRIVALTIME, RONLY, var_ft}, {{flowMIB, 2, 1, 1,70/*,RSX,TMX,FTX*/}, 11,STRING, FTTOTURNAROUNDTIME1, RONLY, var_ft}, {{flowMIB, 2, 1, 1,71/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMTURNAROUNDTIME1, RONLY, var_ft}, {{flowMIB, 2, 1, 1,72/*,RSX,TMX,FTX*/}, 11,STRING, FTTOBITRATE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,73/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMBITRATE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,74/*,RSX,TMX,FTX*/}, 11,STRING, FTTOPDURATE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,75/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMPDURATE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,76/*,RSX,TMX,FTX*/}, 11,STRING, FTTOTCPTIME, RONLY, var_ft}, {{flowMIB, 2, 1, 1,77/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMTCPTIME, RONLY, var_ft}, {{flowMIB, 2, 1, 1,78/*,RSX,TMX,FTX*/}, 11,STRING, FTTOTCPSIZE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,79/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMTCPSIZE, RONLY, var_ft}, {{flowMIB, 2, 1, 1,80/*,RSX,TMX,FTX*/}, 11,STRING, FTTOTCPRATE1, RONLY, var_ft}, {{flowMIB, 2, 1, 1,81/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMTCPRATE1, RONLY, var_ft}, {{flowMIB, 2, 1, 1,82/*,RSX,TMX,FTX*/}, 11,STRING, FTTOTCPRATE2, RONLY, var_ft}, {{flowMIB, 2, 1, 1,83/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMTCPRATE2, RONLY, var_ft}, {{flowMIB, 2, 1, 1,84/*,RSX,TMX,FTX*/}, 11,STRING, FTTOTURNAROUNDTIME2, RONLY, var_ft}, {{flowMIB, 2, 1, 1,85/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMTURNAROUNDTIME2, RONLY, var_ft}, {{flowMIB, 2, 1, 1,86/*,RSX,TMX,FTX*/}, 11,STRING, FTTOTURNAROUNDTIME3, RONLY, var_ft}, {{flowMIB, 2, 1, 1,87/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMTURNAROUNDTIME3, RONLY, var_ft}, {{flowMIB, 2, 1, 1,88/*,RSX,TMX,FTX*/}, 11,STRING, FTTOTURNAROUNDTIME4, RONLY, var_ft}, {{flowMIB, 2, 1, 1,89/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMTURNAROUNDTIME4, RONLY, var_ft}, {{flowMIB, 2, 1, 1,90/*,RSX,TMX,FTX*/}, 11,STRING, FTTOFLOWOCTETS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,91/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMFLOWOCTETS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,92/*,RSX,TMX,FTX*/}, 11,STRING, FTTOFLOWPDUS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,93/*,RSX,TMX,FTX*/}, 11,STRING, FTFROMFLOWPDUS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,94/*,RSX,TMX,FTX*/}, 11,STRING, FTFLOWTIME, RONLY, var_ft}, #endif /* NEW_ATR */ #if NF_OTHER_ATT {{flowMIB, 2, 1, 1,112/*,RSX,TMX,FTX*/}, 11,INTEGER, FTMETERID, RONLY, var_ft}, #endif #if NF_ASN_ATT {{flowMIB, 2, 1, 1,113/*,RSX,TMX,FTX*/}, 11,STRING, FTLOWROUTEASN, RONLY, var_ft}, {{flowMIB, 2, 1, 1,114/*,RSX,TMX,FTX*/}, 11,INTEGER, FTLOWROUTEPREFIX, RONLY, var_ft}, {{flowMIB, 2, 1, 1,115/*,RSX,TMX,FTX*/}, 11,STRING, FTHIROUTEASN, RONLY, var_ft}, {{flowMIB, 2, 1, 1,116/*,RSX,TMX,FTX*/}, 11,INTEGER, FTHIROUTEPREFIX, RONLY, var_ft}, #endif {{flowMIB, 2, 1, 1,118/*,RSX,TMX,FTX*/}, 11,INTEGER, FTDSCODEPOINT, RONLY, var_ft}, #if NEW_ATR {{flowMIB, 2, 1, 1,121/*,RSX,TMX,FTX*/}, 11,INTEGER, FTTOLOSTPDUS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,122/*,RSX,TMX,FTX*/}, 11,INTEGER, FTFROMLOSTPDUS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,123/*,RSX,TMX,FTX*/}, 11,INTEGER, FTTOPQOVERFLOWS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,124/*,RSX,TMX,FTX*/}, 11,INTEGER, FTFROMPQOVERFLOWS, RONLY, var_ft}, {{flowMIB, 2, 1, 1,125/*,RSX,TMX,FTX*/}, 11,STRING, FTTCPDATA, RONLY, var_ft}, #endif /* NEW_ATR */ /* {{flowMIB, 2, 3, 1, 1, PSS,RSX,TMX,FTX },11, STRING, PTSELECTOR, NOACCESS, var_package}, */ /* {{flowMIB, 2, 3, 1, 2, PSS,RSX,TMX,FTX },11, INTEGER, PTRULESET, NOACCESS, var_package}, */ /* {{flowMIB, 2, 3, 1, 3, PSS,RSX,TMX,FTX },11, TIMETICKS, PTTIME, NOACCESS, var_package}, */ /* {{flowMIB, 2, 3, 1, 4, PSS,RSX,TMX,FTX },11, INTEGER, PTINDEX, NOACCESS, var_package}, */ {{flowMIB, 2, 3, 1, 5/*,PSS,RSX,TMX,FTX*/},11, STRING, PTPACKAGE, RONLY, var_package}, /* {{flowMIB, 3, 1, 1, 1, RSX,RNX }, 11,INTEGER, RTRULESET, NOACCESS, var_rt}, */ /* {{flowMIB, 3, 1, 1, 2, RSX,RNX }, 11,INTEGER, RTRULEINDEX, NOACCESS, var_rt}, */ {{flowMIB, 3, 1, 1, 3/*,RSX,RNX*/}, 11,INTEGER, RTSELECTOR, RWRITE, var_rt}, {{flowMIB, 3, 1, 1, 4/*,RSX,RNX*/}, 11,STRING, RTRULEMASK, RWRITE, var_rt}, {{flowMIB, 3, 1, 1, 5/*,RSX,RNX*/}, 11,STRING, RTMATCHVALUE, RWRITE, var_rt}, {{flowMIB, 3, 1, 1, 6/*,RSX,RNX*/}, 11,INTEGER, RTRULEACTION, RWRITE, var_rt}, {{flowMIB, 3, 1, 1, 7/*,RSX,RNX*/}, 11,INTEGER, RTJUMPINDEX, RWRITE, var_rt}, {{U_AUCKLAND, 1, 1}, 9, INTEGER, MSSTATSRESET, RWRITE, var_system}, {{U_AUCKLAND, 1, 2}, 9, INTEGER, MSSTATSTIME, RONLY, var_system}, {{U_AUCKLAND, 1, 3}, 9, INTEGER, MSNPACKETS, RONLY, var_system}, {{U_AUCKLAND, 1, 4}, 9, INTEGER, MSTBACKLOG, RONLY, var_system}, {{U_AUCKLAND, 1, 5}, 9, INTEGER, MSMXPKTRATE, RONLY, var_system}, {{U_AUCKLAND, 1, 6}, 9, INTEGER, MSMXBACKLOG, RONLY, var_system}, {{U_AUCKLAND, 1, 7}, 9, INTEGER, MSNFLOWS, RONLY, var_system}, {{U_AUCKLAND, 1, 8}, 9, INTEGER, MSFLOWSRCV, RONLY, var_system}, {{U_AUCKLAND, 1, 9}, 9, INTEGER, MSNMATCHES, RONLY, var_system}, {{U_AUCKLAND, 1, 10}, 9, INTEGER, MSHASHSRCHS, RONLY, var_system}, {{U_AUCKLAND, 1, 11}, 9, INTEGER, MSHASHCMPS, RONLY, var_system}, {{U_AUCKLAND, 1, 12}, 9, INTEGER, MSTHASHSZ, RONLY, var_system}, {{U_AUCKLAND, 1, 13}, 9, INTEGER, MSNHASHENTS, RONLY, var_system}, {{U_AUCKLAND, 1, 14}, 9, INTEGER, MSGCINTERVAL, RWRITE, var_system}, {{U_AUCKLAND, 1, 15}, 9, INTEGER, MAX_FLOWS, RONLY, var_system}, {{U_AUCKLAND, 1, 16}, 9, INTEGER, MSAVIDLEPER1000, RONLY, var_system}, {{U_AUCKLAND, 1, 17}, 9, INTEGER, MSMINIDLEPER1000, RONLY, var_system}, {{U_AUCKLAND, 1, 18}, 9, STRING, INTERFACENAME, RONLY, var_system}, {{U_AUCKLAND, 2, 1}, 9, INTEGER, PCNEARMEM, RONLY, var_system}, {{U_AUCKLAND, 2, 2}, 9, INTEGER, PCFARMEM, RONLY, var_system}, {{U_AUCKLAND, 2, 3}, 9, INTEGER, PCBADPKTS, RONLY, var_system}, {{U_AUCKLAND, 2, 4}, 9, INTEGER, PCNOBUFPKTS, RONLY, var_system}, {{U_AUCKLAND, 2, 5}, 9, INTEGER, PCLOSTPKTS, RONLY, var_system}, {{U_AUCKLAND, 2, 6}, 9, INTEGER, PCBADTIMES, RONLY, var_system}, {{U_AUCKLAND, 3, 1}, 9, INTEGER, TR_STATE, RWRITE, var_system}, {{U_AUCKLAND, 3, 2}, 9, STRING, TR_INFO, RONLY, var_system}, {{U_AUCKLAND, 3, 3}, 9, INTEGER, TR_TIME, RONLY, var_system} }; int compare( oid *name1, int len1, oid *name2, int len2) { int len = len1 < len2 ? len1 : len2; while(len-- > 0) { /* Find first non-matching byte */ if (*name1 < *name2) return -1; if (*name2++ < *name1++) return 1; } /* Bytes match up to length of shorter string */ if (len1 < len2) return -1; /* name1 shorter, so it is "less" */ if (len2 < len1) return 1; return 0; /* Both strings are equal */ } oid newname[MAX_NAME_LEN]; /* Used in all the var_* functions */ int set_request; /* True if this is a SET_REQ_MSG pdu */ /* * getStatPtr - return a pointer to the named variable, as well as it's * type, length, and access control list. * * If an exact match for the variable name exists, it is returned. If not, * and exact is false, the next variable lexicographically after the * requested one is returned. * * If no appropriate variable can be found, NULL is returned. */ u_char *getStatPtr( oid *name, /* IN: name of var, OUT: name matched */ int *namelen, /* IN: nbr sub-ids in name, OUT: sub-ids in matched name */ u_char *type, /* OUT: type of matched variable */ int *len, /* OUT: length of matched variable */ u_short *acl, /* OUT: access control list */ int exact, /* IN: TRUE if exact match wanted */ write_fn_type *write_method, /* OUT: 1 if function, 0 if char * */ struct packet_info *pi, int *noSuchObject) { struct variable *vp; u_char *access; int x, result, b,t; u_short cname[MAX_NAME_LEN]; t = *namelen <= MAX_NAME_LEN ? *namelen : MAX_NAME_LEN; for (x = 0; x != t; ++x) /* Make u_short copy of vbl name */ cname[x] = name[x]; *write_method = NULL; /* Find start row for variables[] search */ b = 0; t = sizeof(variables)/sizeof(struct variable) - 1; do { /* Binary search averages about 6 compares instead of 22 */ x = (b + t)/2; vp = &variables[x]; result = memcmp((u_char *)cname, (u_char *)vp->name, sizeof(u_short)* (*namelen < (int)vp->namelen ? *namelen : (int)vp->namelen)); if (result <= 0) t = x-1; /* Move top down */ else b = x+1; /* Move bottom up */ } while (b <= t); #ifdef PSTESTING printf("getStatPtr binary: x=%d, b=%d, t=%d\n", x,b,t); #endif set_request = pi->pdutype == SET_REQ_MSG; for (x = t < 0 ? 0 : t, vp = &variables[x]; x < sizeof(variables)/sizeof(struct variable); ++vp, ++x) { /* Find first vp entry >= requested one */ result = memcmp((u_char *)vp->name, (u_char *)cname, sizeof(u_short)* ((int)vp->namelen < *namelen ? (int)vp->namelen : *namelen)); if (result < 0) continue; /* Not there yet */ for (b = 0; b != (int)vp->namelen; ++b) /* Make oid name for vp */ newname[b] = (oid)vp->name[b]; *len = 0; access = (*(vp->findVar))(vp, name, namelen, exact, len, write_method); #ifdef PSTESTING printf("getStatPtr linear: x=%d, result=%d, *len=%d\n", x,result,*len); #endif *type = vp->type; *acl = vp->acl; if (access != NULL) { /* access points to object value */ *noSuchObject = FALSE; return access; } if (exact) { /* Matched up to vp->namelen */ *noSuchObject = *write_method == NULL; /* If we have a write method, we can create the object */ return NULL; } if (*len != 0) { /* Object found, was too big */ *noSuchObject = FALSE; return NULL; } /* Not exact (i.e. GETNEXT or GETBULK); keep looking */ } *noSuchObject = TRUE; #ifdef TESTING printf("getStatPtr failed\n"); #endif return NULL; } extern Bit32 snmp_peer_addr; /* Declared in meter_pc.c */ void display_msg(int timestamp, char *msg) { #ifdef DOS if (display_enabled) { scpos(0,scr_lrow); if (timestamp) printf("%02d%02d:%02d ", tod_h,tod_m,tod_s); else printf(" "); printf(msg); w_roll(0,7, scr_chrtcol-1,scr_lrow, 1); } #else time_t t; char *ts; if (display_enabled) { if (timestamp) { time(&t); ts = ctime(&t); printf("%c%c%c%c:%c%c ", ts[11],ts[12],ts[14],ts[15], ts[17],ts[18]); } else printf(" "); printf("%s\n",msg); } #endif } void log_msg(int priority, int die, char *fmt, ...) { /* priority = LOG_ERR, LOG_WARNING, LOG_INFO, LOG_DEBUG (LOG_INFO messages aren't written to local log file) die = +1 to exit, 0 normally, -1 to leave log_file open */ char msg[300]; /* Longest log message ~ 130, 13 Mar 01 !!! */ va_list ap; #if !defined(DOS) time_t t; char *ts, ftb[32]; #endif #if defined(LOG_LOCAL) && !defined(DOS) va_start(ap, fmt); if (*syslog_name) vsyslog(priority, fmt, ap); #endif va_start(ap, fmt); vsprintf(msg, fmt, ap); va_end(ap); #if !defined(DOS) /* Write message to log file */ if (priority != LOG_INFO) { if (log_file == NULL) { if ((log_file = fopen(logname,"a")) == NULL) { fprintf(stderr,"Failed to open logfile '%s':%s\n", logname, strerror(errno)); exit(321); /* Don't try to run without log file! */ } } if (log_file != NULL) { time(&t); ts = ctime(&t); strncpy(&ftb[0], &ts[11], 9); /* 17:31:42_ */ strncpy(&ftb[9], &ts[0], 4); /* Thu_ */ strncpy(&ftb[13], &ts[8], 3); /* 23_ */ strncpy(&ftb[16], &ts[4], 4); /* Sep_ */ strncpy(&ftb[20], &ts[20], 4); /* 1997 */ ftb[24] = '\0'; fprintf(log_file,"%s (%2d): %s\n", ftb, priority, msg); } if (die >= 0) { fclose(log_file); log_file = NULL; } } #endif display_msg(1,msg); if (die > 0) stop_meter(die); } int alloc_rulespace(int rs, int rules, Bit16 size) { /* rules=1 to alloc rules space, =0 to alloc rule hash space */ if (rs > MXRTBLS || rs < 1 || (rs == 1 && rules)) { log_msg(LOG_ERR, 0, "Alloc invalid rs ix !!!"); return 0; } if (rules) { if (inuse_rules+size > mxrules) { log_msg(LOG_ERR, 0, "ri[%d]: No room for ruleset", rs); return 0; } ri[rs-1].ri_Size = size; ri[rs-1].ri_rule_offset = inuse_rules; ri[rs-1].ri_rule_table = &rule_space[inuse_rules]; inuse_rules += size; } else { /* rule hash table */ if (inuse_rule_hash+size > mxrulehash) { log_msg(LOG_ERR, 0, "ri[%d]: No room for rule hash", rs); return 0; } ri[rs-1].ri_rule_hash_size = size; ri[rs-1].ri_rule_hash_offset = inuse_rule_hash; ri[rs-1].ri_rule_hash = &rule_hash_space[inuse_rule_hash]; inuse_rule_hash += size; } return 1; } int free_rulespace(int rs) { struct rtinf_rec *rip; Bit32 rule_offset, rule_sz; Bit32 hash_offset, hash_sz; int j; if (rs < 1 || rs > MXRTBLS) { log_msg(LOG_ERR, 0, "Free invalid rs ix (%d)", rs); return 0; } if (rs == 1) return 1; rip = &ri[rs-1]; rule_offset = rip->ri_rule_offset; rule_sz = rip->ri_Size; hash_offset = rip->ri_rule_hash_offset; hash_sz = rip->ri_rule_hash_size; for (j = 1; j != MXRTBLS; ++j) { if (j == rs-1) continue; rip = &ri[j]; if (rip->ri_rule_offset > rule_offset) { rip->ri_rule_offset -= rule_sz; rip->ri_rule_table = &rule_space[rip->ri_rule_offset]; } if (rip->ri_rule_hash_offset > hash_offset) { rip->ri_rule_hash_offset -= hash_sz; rip->ri_rule_hash = (Bit16 huge *)&rule_hash_space[rip->ri_rule_hash_offset]; } } if (rule_offset+rule_sz != inuse_rules) /* Not the top ruleset */ memcpy(&rule_space[rule_offset], &rule_space[rule_offset+rule_sz], (inuse_rules-rule_offset-rule_sz)*sizeof(struct rule)); inuse_rules -= rule_sz; if (hash_offset+hash_sz != inuse_rule_hash) /* Not the top rule hash */ memcpy(&rule_hash_space[hash_offset], &rule_hash_space[hash_offset+hash_sz], (inuse_rule_hash-hash_offset-hash_sz)*sizeof(Bit16)); inuse_rule_hash -= hash_sz; /* free_rulespace() is only called by set_RowStatus/RS_DESTROY, so we don't bother to reset these things here .. rip->ri_Size = rip->ri_rule_offset = rip->ri_rule_hash_size = rip->ri_rule_hash_offset = 0; Nevil, 17 May 99 */ return 1; } u_char *var_system( /* System (MIB 2 and UA) variables */ struct variable *vp, oid *name, int *length, int exact, int *var_len, write_fn_type *write_method) { #ifndef DOS struct timeval now, boottime; #endif int result; unsigned long ul; newname[vp->namelen] = 0; result = compare(newname,(int)vp->namelen+1, name,*length); if ((exact && (result != 0)) || (!exact && (result <= 0))) return NULL; memcpy((u_char *)name, (u_char *)newname, ((int)vp->namelen+1)*sizeof(oid)); *length = vp->namelen+1; *var_len = sizeof(retval); /* Default length */ switch (vp->magic){ case VERSION_DESCR: *var_len = strlen(version_descr); return (u_char *)version_descr; case VERSION_ID: *var_len = sizeof(version_id); return (u_char *)version_id; case UPTIME: retval = uptime_cs(); return (u_char *)&retval; case IFNUMBER: retval = 1; /* 1 ethernet card to start with */ return (u_char *)&retval; case FLOODMARK: *var_len = sizeof(FloodMark); return (u_char *)&FloodMark; case INACT_TIMEOUT: *var_len = sizeof(InactivityTimeout); return (u_char *)&InactivityTimeout; case ACTIVE_FLOWS: retval = active_flows(); return (u_char *)&retval; case MAX_FLOWS: retval = mxflows; /* Set at meter startup */ return (u_char *)&retval; case FLOOD_MODE: *var_len = sizeof(FloodMode); return (u_char *)&FloodMode; case MSSTATSRESET: *write_method = &writeStatsReset; retval = 0; return (u_char *)&retval; case MSSTATSTIME: *var_len = sizeof(stats_time); return (u_char *)&stats_time; case MSNPACKETS: *var_len = sizeof(npackets); return (u_char *)&npackets; case MSTBACKLOG: *var_len = sizeof(t_backlog); return (u_char *)&t_backlog; case MSMXPKTRATE: *var_len = sizeof(max_pkt_rate); return (u_char *)&max_pkt_rate; case MSMXBACKLOG: *var_len = sizeof(max_pkt_backlog); return (u_char *)&max_pkt_backlog; case MSNFLOWS: *var_len = sizeof(nflows); return (u_char *)&nflows; case MSFLOWSRCV: *var_len = sizeof(FlowsRecovered); return (u_char *)&FlowsRecovered; case MSNMATCHES: *var_len = sizeof(n_matches); return (u_char *)&n_matches; case MSHASHSRCHS: *var_len = sizeof(n_hash_searches); return (u_char *)&n_hash_searches; case MSHASHCMPS: *var_len = sizeof(n_hash_compares); return (u_char *)&n_hash_compares; case MSTHASHSZ: *var_len = sizeof(fthashmod); return (u_char *)&fthashmod; case MSNHASHENTS: *var_len = sizeof(n_hash_ents); return (u_char *)&n_hash_ents; case MSGCINTERVAL: *var_len = sizeof(gc_interval); return (u_char *)&gc_interval; case MSAVIDLEPER1000: #ifdef DOS # if OCX_MON || OC3_MON retval = 0; # else retval = kilodummypackets; if (dummypackets >= 500) ++retval; ul = retval+npackets/1000L; if (ul == 0) retval = 0; /* Avoid divide by 0 */ else retval = retval*1000L/ul; # endif #else ul = realtime-realtime_org; if (ul == 0) retval = 0; else retval = 1000 - (proctime-proctime_org)*1000/ul; #endif return (u_char *)&retval; case MSMINIDLEPER1000: #ifdef DOS # if OCX_NTM || OC3_NTM retval = 0; # else ul = (mindummyrate+mdpacketrate)*10L; if (ul == 0) retval = 0; /* Avoid divide by 0 */ else retval = (mindummyrate*10000L+5L)/ul; # endif #else retval = min_idle1000; #endif return (u_char *)&retval; #ifdef DOS case PCNEARMEM: retval = (Bit32)coreleft(); return (u_char *)&retval; case PCFARMEM: retval = (Bit32)farcoreleft(); return (u_char *)&retval; case PCBADPKTS: *var_len = sizeof(badpackets); return (u_char *)&badpackets; case PCNOBUFPKTS: *var_len = sizeof(nobufpackets); return (u_char *)&nobufpackets; case PCLOSTPKTS: retval = noflowpackets-pc_noflowpkts + /* No memory for flow (flowhash.c) */ nobufpackets + /* No Waterloo TCP buffer available (src\pcpkt.c) */ badpackets + /* Packet length > BUFSIZE (src\pcpkt.c) */ lostpackets; /* No pkt buffer available (meter_pc.c) */ return (u_char *)&retval; #else case PCLOSTPKTS: pkt_counts(0); retval = lostpackets+noflowpackets; return (u_char *)&retval; #endif case PCBADTIMES: retval = bad_uptimes; return (u_char *)&retval; case INTERFACENAME: *var_len = strlen(interface_name); return (u_char *)interface_name; #if CR_DATA || DAG_DIRECT case TR_STATE: *var_len = sizeof(trace_state); /* If we want the default write routine, */ return (u_char *)&trace_state; /* we must refer to the actual variable */ #endif case TR_INFO: /* Null if meter doesn't read trace files */ *var_len = strlen(crl_info); return (u_char *)crl_info; case TR_TIME: retval = last_t_sec; return (u_char *)&retval; default: *var_len = 0; ERROR(""); } return NULL; } int string_OK(int t) { if (t != STRING) { log_msg(LOG_ERR, 0, "Not string"); return FALSE; } return TRUE; } int int_OK(int t) { if (t != INTEGER) { log_msg(LOG_ERR, 0, "Not integer"); return FALSE; } return TRUE; } int tr_status(int tbl, int x) { switch (tbl) { case 1: /* Rule Info table */ return ri[x-1].ri_Status; case 3: /* Reader Info table */ return ci[x-1].ci_Status; case 4: /* Manager Info table */ return mi[x-1].mi_Status; } return RS_UNUSED; } void set_tr_timestamp(int tbl, int x) { switch (tbl) { case 1: /* Rule Info table */ ri[x-1].ri_TimeStamp = uptime_cs(); break; case 4: /* Manager Info table */ mi[x-1].mi_TimeStamp = uptime_cs(); break; } } void recover_flows(int rs) { struct flow huge *fp; int k; for (k = 1; k <= mxflows; ++k) { if (flow_idle(k)) continue; #if FLOW_INDEX fp = flow_ix[k-1]; #else fp = &fa[k-1]; #endif if (fp->FlowRuleSet != rs) continue; /* Not this ruleset */ mark_idle(k); free_flow(fp); --ri[rs-1].ri_FlowRecords; --nflows; ++FlowsRecovered; } /* recover_flows() is only called by set_RowStatus/RS_DESTROY, ri[rs-1].ri_flow_chain is reset there. (It wasn't being reset at all, which caused strange problems when a ruleset info row was reused!) Nevil, 17 May 99 */ } void build_rdr_chains(char p) /* Chain reader rows using same ruleset */ { /* For nifty */ int j, r; struct rdr_rec *cip; int rs_rdr_tail[MXRTBLS]; memset(rs_rdr, 0, sizeof(rs_rdr)); memset(rs_rdr_tail, 0, sizeof(rs_rdr_tail)); for (j = 0; j != MXCLCTRS; ++j) { cip = &ci[j]; if (cip->ci_RuleSet != 0) { if (rs_rdr[r = cip->ci_RuleSet-1] == NULL) rs_rdr[r] = cip; else ci[rs_rdr_tail[r]].ci_rs_next = cip; rs_rdr_tail[r] = j; cip->ci_rs_next = NULL; } } #if 0 printf("B_R_C(%c): Checking rdr info table ..\n", p); for (j = 0; j != MXRTBLS; ++j) { if (rs_rdr[j] != NULL) { printf( " j=%d, rs_rdr[%d]=%x, rs=%d, owner=%s, MinPDUs=%d, ci_next=%x\n", j, j,rs_rdr[j], rs_rdr[j]->ci_RuleSet, rs_rdr[j]->ci_Owner, rs_rdr[j]->ci_MinPDUs, rs_rdr[j]->ci_rs_next); for (cip = rs_rdr[j]; ; ) { r = cip - ci; /* GNU cc gives ptr diff in elemnts! */ printf(" row=%d, owner=%s, MinPDUs=%d, ci_next=%x\n", r, cip->ci_Owner, cip->ci_MinPDUs, cip->ci_rs_next); if ((cip = cip->ci_rs_next) == NULL) break; } } } fflush(stdout); #endif } /* RowStatus actions are .. RESERVE1: Check types, lengths and values (GETs and SETs) RESERVE2: Ditto (only performed for SETs) COMMIT: Do the set ACTION: Execute any actions FREE: Undo anything done by RESERVE1 and RESERVE2 */ int status_change_OK(int s_new, int s_old) { switch (s_new) { case RS_ACTIVE: if (s_old == RS_UNUSED) return SNMP_ERR_NOCREATION; if (s_old != RS_NOTINSERVICE && s_old != RS_NOTREADY && s_old != RS_SET_CREATE) return SNMP_ERR_INCONSISTENTVALUE; break; case RS_NOTINSERVICE: if (s_old == RS_UNUSED) return SNMP_ERR_NOCREATION; if (s_old != RS_ACTIVE && s_old != RS_NOTINSERVICE) return SNMP_ERR_INCONSISTENTVALUE; break; case RS_NOTREADY: return SNMP_ERR_INCONSISTENTVALUE; case RS_CREATEANDGO: case RS_CREATEANDWAIT: if (s_old != RS_UNUSED) return SNMP_ERR_INCONSISTENTVALUE; case RS_DESTROY: break; } return SNMP_ERR_NOERROR; } int set_RowStatus(int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int bigsize = 1000, which, row, r; Int32 reqval; struct rtinf_rec *rip; struct rdr_rec *cip; struct mgr_rec *mip; which = name[8]; row = name[11]; if (!int_OK(var_val_type)) return SNMP_ERR_WRONGTYPE; asn_parse_int(var_val, &bigsize, &var_val_type, (Bit32 *)&reqval, sizeof(reqval)); if (reqval < RS_UNUSED || reqval > RS_DESTROY) return SNMP_ERR_INCONSISTENTVALUE; switch(which) { case 1: /* Rule info table */ rip = &ri[row-1]; break; case 3: /* Reader info table */ cip = &ci[row-1]; break; case 4: /* Manager info table */ mip = &mi[row-1]; break; } if (action == RESERVE2) { switch(which) { case 1: /* Rule info table */ rip->ri_old_status = rip->ri_Status; if (reqval == RS_DESTROY) { if (row == 1) /* Can't destroy default ruleset! */ return SNMP_ERR_INCONSISTENTVALUE; return rip->ri_running != 0 ? SNMP_ERR_INCONSISTENTVALUE : SNMP_ERR_NOERROR; } else { rip->ri_Status = RS_SET_CREATE; r = status_change_OK(reqval, rip->ri_old_status); if (r == SNMP_ERR_NOERROR && reqval == RS_ACTIVE && rip->ri_old_status == RS_NOTINSERVICE) { if (rip->ri_Size == 0) /* No rules downloaded! */ return SNMP_ERR_INCONSISTENTVALUE; if (!optimise_rule_table(row)) /* Build rule hash tables */ return SNMP_ERR_RESOURCEUNAVAILABLE; else { log_msg(LOG_WARNING, 0, "ri[%d]: '%s', rhss = %u", row, rip->ri_Name,rip->ri_rule_hash_size); } } return r; } case 3: /* Reader info table */ cip->ci_old_status = cip->ci_Status; cip->ci_Status = RS_SET_CREATE; return status_change_OK(reqval, cip->ci_old_status); case 4: /* Manager info table */ mip->mi_old_status = mip->mi_Status; mip->mi_Status = RS_SET_CREATE; return status_change_OK(reqval, mip->mi_old_status); } } else if (action == FREE) { switch(which) { case 1: /* Rule info table */ rip->ri_Status = rip->ri_old_status; break; case 3: /* Reader Info table */ cip->ci_Status = cip->ci_old_status; break; case 4: /* Manager Info table */ mip->mi_Status = mip->mi_old_status; break; } return SNMP_ERR_NOERROR; } else if (action == COMMIT) { switch(which) { case 1: /* Rule info table */ switch (reqval) { case RS_ACTIVE: rip->ri_Status = RS_ACTIVE; break; case RS_NOTINSERVICE: rip->ri_Status = RS_NOTINSERVICE; break; case RS_CREATEANDGO: case RS_CREATEANDWAIT: rip->ri_Status = reqval == RS_CREATEANDGO ? RS_ACTIVE : RS_NOTINSERVICE; /* notready = missing info needed by agent */ /* Don't recover rules or hash tables */ break; case RS_DESTROY: if (rip->ri_FlowRecords != 0) recover_flows(row); /* 1-org */ free_rulespace(row); /* Recover rule space */ /* Reset row info variables. Nevil, 17 May 99 */ memset(rip, 0, sizeof(struct rtinf_rec)); rip->ri_Status = RS_UNUSED; break; } break; case 3: /* Reader info table */ switch (reqval) { case RS_ACTIVE: cip->ci_Status = RS_ACTIVE; break; case RS_NOTINSERVICE: cip->ci_Status = RS_NOTINSERVICE; break; case RS_CREATEANDGO: case RS_CREATEANDWAIT: cip->ci_Status = reqval == RS_CREATEANDGO ? RS_ACTIVE : RS_NOTINSERVICE; break; case RS_DESTROY: memset(cip, 0, sizeof(struct rdr_rec)); cip->ci_Status = RS_UNUSED; build_rdr_chains('D'); /* For nifty */ break; } break; case 4: /* Manager info table */ switch (reqval) { case RS_ACTIVE: mip->mi_Status = RS_ACTIVE; break; case RS_NOTINSERVICE: mip->mi_Status = RS_NOTINSERVICE; break; case RS_CREATEANDGO: case RS_CREATEANDWAIT: mip->mi_Status = reqval == RS_CREATEANDGO ? RS_ACTIVE : RS_NOTINSERVICE; break; case RS_DESTROY: if (mip->mi_RunningStandby == TV_FALSE) open_rule_set(mip->mi_CurrentRuleSet, 0); else open_rule_set(mip->mi_StandbyRuleSet, 0); memset(mip, 0, sizeof(struct mgr_rec)); mip->mi_RunningStandby = TV_FALSE; mip->mi_Status = RS_UNUSED; break; } break; } set_tr_timestamp(which, row); } return SNMP_ERR_NOERROR; } int set_Name(int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int size, bigsize = 1000, which, row; u_char buf[30]; if (!string_OK(var_val_type)) return SNMP_ERR_WRONGTYPE; size = sizeof(buf); asn_parse_string(var_val, &bigsize, &var_val_type, buf, &size); if (size > NAMESZ) { log_msg(LOG_ERR, 0, "Name too long"); return SNMP_ERR_WRONGLENGTH; } which = name[8]; row = name[11]; if (action == RESERVE2) { return tr_status(which, row) == RS_UNUSED ? SNMP_ERR_NOCREATION : SNMP_ERR_NOERROR; } else if (action == COMMIT) { memset(statP, 0, NAMESZ+1); memcpy(statP, buf, size); set_tr_timestamp(which, row); } return SNMP_ERR_NOERROR; } int set_Integer(int action, u_char *var_val, /* Sets a value in an info row */ u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int bigsize = 1000, which, row; Int32 reqval; if (!int_OK(var_val_type)) return SNMP_ERR_WRONGTYPE; asn_parse_int(var_val, &bigsize, &var_val_type, (Bit32 *)&reqval, sizeof(reqval)); which = name[8]; row = name[11]; if (action == RESERVE2) { return tr_status(which, row) == RS_UNUSED ? SNMP_ERR_NOCREATION : SNMP_ERR_NOERROR; } else if (action == COMMIT) { *((int *)statP) = (int)reqval; set_tr_timestamp(which, row); } return SNMP_ERR_NOERROR; } int set_RuleSize(int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int bigsize = 1000, j, ri_row; Bit32 intval = 0, memory_size; struct rtinf_rec *rip; struct rule huge *rt; if (!int_OK(var_val_type)) return SNMP_ERR_WRONGTYPE; ri_row = name[11]; if (ri_row == 1) { log_msg(LOG_ERR, 0, "Can't modify default rules"); return SNMP_ERR_INCONSISTENTVALUE; } rip = &ri[ri_row-1]; if (rip->ri_running != 0) { log_msg(LOG_ERR, 0, "Can't modify running ruleset"); return SNMP_ERR_INCONSISTENTVALUE; } asn_parse_int(var_val, &bigsize, &var_val_type, &intval, sizeof(intval)); if (action == RESERVE2) { if (rip->ri_Status == RS_UNUSED) return SNMP_ERR_NOCREATION; if (intval > 0xFFFF) /* Won't fit in a Bit16 */ return SNMP_ERR_INCONSISTENTVALUE; if (!alloc_rulespace(ri_row, 1, intval)) /* Space for rules */ return SNMP_ERR_RESOURCEUNAVAILABLE; rip->ri_Size = intval; memset(rip->ri_rule_table, 0, sizeof(struct rule)*rip->ri_Size); } else if (action == COMMIT) { set_tr_timestamp(1, ri_row); /* RuleInfo TimeStamp */ log_msg(LOG_WARNING, 0, "ri[%d]: '%s', %d rules", ri_row, rip->ri_Name,rip->ri_Size); } return SNMP_ERR_NOERROR; } int set_RuleSet(int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int bigsize = 1000, row, which, s,c; Bit32 intval = 0; struct mgr_rec *mip; if (!int_OK(var_val_type)) return SNMP_ERR_WRONGTYPE; asn_parse_int(var_val, &bigsize, &var_val_type, &intval, sizeof(intval)); which = name[10]; row = name[11]; mip = &mi[row-1]; if (action == RESERVE2) { if (mip->mi_Status == RS_UNUSED) return SNMP_ERR_NOCREATION; if (which == 9) { /* RunningStandby */ if (intval != TV_TRUE && intval != TV_FALSE) return SNMP_ERR_INCONSISTENTVALUE; } else { if (intval < 1 || intval > MXRTBLS) { log_msg(LOG_ERR, 0, "Bad RuleSet index (%d)", intval); return SNMP_ERR_INCONSISTENTVALUE; } if (ri[intval-1].ri_Status != RS_ACTIVE) { log_msg(LOG_ERR, 0, "Rules not ready"); return SNMP_ERR_RESOURCEUNAVAILABLE; } } } if (action == COMMIT) { if (which == 2) { /* CurrentRuleSet */ if ((c = mip->mi_CurrentRuleSet) == intval) return SNMP_ERR_NOERROR; /* No change needed */ if (mip->mi_RunningStandby == TV_FALSE) { open_rule_set(c,0); /* Close old current ruleset */ open_rule_set(intval, 1); /* Open new one */ } /* else running standby; just set CurrentRuleSet */ mip->mi_CurrentRuleSet = intval; log_msg(LOG_WARNING, 0, "Manager %d, Current set %d", row,(int)intval); #if CR_DATA || DAG_DIRECT /* Can read a trace file */ if (trace_state == CT_WAIT_RULES) trace_state = CT_RULES_READY; #endif } else if (which == 3) { /* StandbyRuleSet */ if ((s = mip->mi_StandbyRuleSet) == intval) return SNMP_ERR_NOERROR; /* No change needed */ if (mip->mi_RunningStandby == TV_TRUE) { open_rule_set(s,0); /* Close old standby ruleset */ open_rule_set(intval, 1); /* Open new one */ } /* else running current; just set StandbyRuleSet */ mip->mi_StandbyRuleSet = intval; log_msg(LOG_WARNING, 0, "Manager %d, Standby set %d", row,(int)intval); } else { /* 9 -> RunningStandby */ if (intval != mip->mi_RunningStandby) { c = mip->mi_CurrentRuleSet; s = mip->mi_StandbyRuleSet; if (mip->mi_RunningStandby == TV_TRUE) { /* Switch to current */ open_rule_set(s,0); open_rule_set(c,1); } else { /* Running current, switch to standby */ open_rule_set(c,0); open_rule_set(s,1); } mip->mi_RunningStandby = intval; log_msg(LOG_WARNING, 0, "Manager %d running %s", row, intval == TV_FALSE ? "Current" : "Standby"); } } } return SNMP_ERR_NOERROR; } int set_ReaderSet(int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int bigsize = 1000, row; Bit32 intval = 0; struct rdr_rec *cip; if (!int_OK(var_val_type)) return SNMP_ERR_WRONGTYPE; asn_parse_int(var_val, &bigsize, &var_val_type, &intval, sizeof(intval)); row = name[11]; cip = &ci[row-1]; if (action == RESERVE2) { if (cip->ci_Status == RS_UNUSED) return SNMP_ERR_NOCREATION; if (intval < 1 || intval > MXRTBLS) return SNMP_ERR_INCONSISTENTVALUE; } if (action == COMMIT) { cip->ci_RuleSet = intval; build_rdr_chains('R'); /* For nifty */ } return SNMP_ERR_NOERROR; } int set_LastTime(int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int row, j, rsx; struct rdr_rec *cip, *cixp; Bit32 min_time; row = name[11]; if (var_val_type != TIMETICKS) return SNMP_ERR_WRONGTYPE; cip = &ci[row-1]; if (cip->ci_Status == RS_UNUSED) return SNMP_ERR_NOCREATION; if (cip->ci_Status != RS_ACTIVE || cip->ci_RuleSet == 0) return SNMP_ERR_RESOURCEUNAVAILABLE; if (action == COMMIT) { cip->ci_PrevTime = cip->ci_LastTime; cip->ci_LastTime = uptime_cs(); rsx = cip->ci_RuleSet; min_time = cip->ci_LastTime < InactivityTimeout ? 0 : cip->ci_LastTime-InactivityTimeout; /* Must be >= 0 */ for (j = 0; j != MXCLCTRS; ++j) { cixp = &ci[j]; if (cixp->ci_Status != RS_ACTIVE || cixp->ci_RuleSet != rsx) continue; /* Not this rule set */ if (cixp->ci_PrevTime < min_time) min_time = cixp->ci_PrevTime; } ri[rsx-1].ri_gc_time = min_time; log_msg(LOG_INFO, 0, "'%s' flows read by %s", ri[rsx-1].ri_Name, cip->ci_Owner); already_complained = 0; /* Let garbage collector run again */ /* build_rdr_chains('L'); /* For nifty testing */ } return SNMP_ERR_NOERROR; } int writeMask(int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int size, bigsize = 1000, j; Bit8 buf[RULE_ADDR_LEN]; struct rule huge *rt, huge *r; if (!string_OK(var_val_type)) return SNMP_ERR_WRONGTYPE; for (j = 0; j != RULE_ADDR_LEN; ++j) buf[j] = 0; size = sizeof(buf); asn_parse_string(var_val, &bigsize, &var_val_type, buf, &size); if (size > var_val_len) { log_msg(LOG_ERR, 0, "Address too big"); return SNMP_ERR_WRONGLENGTH; } for (j = 0; j != n_masks; ++j) { if (memcmp((u_char *)buf,(u_char *)&Masks[j].Val, RULE_ADDR_LEN) == 0) break; } if (j == n_masks && n_masks == MXMASKS) { log_msg(LOG_ERR, 0, "Too many masks"); return SNMP_ERR_RESOURCEUNAVAILABLE; } if (action == COMMIT) { #ifdef H_TEST printf("wrAddr: sz=%d, statP=%Fp, addr=", size, statP); daddr(statP); printf("\n"); #endif if (j == n_masks) { memcpy((u_char *)&Masks[j].Val, (u_char *)buf, RULE_ADDR_LEN); ++n_masks; } rt = ri[name[11]-1].ri_rule_table; r = &rt[name[12]-1]; r->RuleMaskVal = j; } return SNMP_ERR_NOERROR; } int writeStatsReset(int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int bigsize = 1000; Bit32 intval = 0; if (!int_OK(var_val_type)) return SNMP_ERR_WRONGTYPE; asn_parse_int(var_val, &bigsize, &var_val_type, &intval, sizeof(intval)); if (action == COMMIT) zero_stats(1); return SNMP_ERR_NOERROR; } int set_Bit16(int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int bigsize = 1000; Bit32 intval = 0; if (!int_OK(var_val_type)) return SNMP_ERR_WRONGLENGTH; asn_parse_int(var_val, &bigsize, &var_val_type, &intval, sizeof(intval)); if (intval > 0xFFFF) return SNMP_ERR_INCONSISTENTVALUE; if (action == COMMIT) *((Bit16 *)statP) = (Bit16)intval; return SNMP_ERR_NOERROR; } u_char *var_rinfo(struct variable *vp, oid *name, int *length, int exact, int *var_len, write_fn_type *write_method) { int tblsz, t, x; #ifdef TESTING int j, cmp; #endif *write_method = NULL; t = (int)vp->name[8]; if (t == 0 || t >= sizeof(tbl_size)) return NULL; tblsz = tbl_size[t]; x = (int)name[11]; #ifdef TESTING scpos(0,scr_lrow); printf("\nvar_rinfo(): exact=%d, control=%d, x=%d, tblsz=%d, magic=%d\n name=", exact,(int)name[8],x,tblsz,vp->magic); for (j = 0; j != *length; ++j) printf(".%d",name[j]); printf("\n"); #endif if (exact) { if (*length < 12) return NULL; if (x < 1 || x > tblsz) return NULL; newname[11] = (oid)x; if (compare(newname,(int)vp->namelen+1, name,*length) != 0) return NULL; if (tr_status(t,x) == RS_UNUSED) { /* Row not created yet */ if (!set_request) return NULL; /* Read requests fail */ } /* Write requests checked in set_ routines */ } else { if (compare(newname,11, name,11) != 0 || *length < 12) x = 0; for (++x; x <= tblsz; ++x) { newname[11] = (oid)x; #ifdef TESTING cmp = compare(newname,(int)vp->namelen+1, name,*length); printf("x=%d, cmp=%d ", x,cmp); for (j = 0; j != (int)vp->namelen+1; ++j) printf(".%d",newname[j]); printf("\n"); if (cmp > 0) { #else if (compare(newname,(int)vp->namelen+1, name,*length) > 0) { #endif if (tr_status(t,x) != RS_UNUSED) break; } } if (x > tblsz) return NULL; } memcpy((u_char *)name, (u_char *)newname, ((int)vp->namelen+1)*sizeof(oid)); *length = (int)vp->namelen+1; *var_len = sizeof(retval); switch (vp->magic) { case RISTATUS: *write_method = &set_RowStatus; *var_len = sizeof(ri[x-1].ri_Status); return (u_char *)&ri[x-1].ri_Status; case RIRULESIZE: *write_method = &set_RuleSize; *var_len = sizeof(ri[x-1].ri_Size); return (u_char *)&ri[x-1].ri_Size; case RIOWNER: *write_method = &set_Name; *var_len = strlen(ri[x-1].ri_Owner); return (u_char *)ri[x-1].ri_Owner; case RITIMESTAMP: *var_len = sizeof(ri[x-1].ri_TimeStamp); return (u_char *)&ri[x-1].ri_TimeStamp; case RINAME: *write_method = &set_Name; *var_len = strlen(ri[x-1].ri_Name); return (u_char *)ri[x-1].ri_Name; case RIFLOWCOUNT: *var_len = sizeof(ri[x-1].ri_FlowRecords); return (u_char *)&ri[x-1].ri_FlowRecords; case IFACE_RATE: #if defined(DOS) # if OCX_NTM || OC3_NTM retval = 0L; # else retval = en_table[x-1].SampleRate; # endif #else /* Unix */ retval = iface_info(x,IFACE_RATE); #endif return (u_char *)&retval; case IFACE_LOST: #if defined(DOS) # if OCX_NTM || OC3_NTM retval = 0L; /* Don't know how to get these for OCxMON $$$ */ # else retval = en_table[x-1].lostpackets + en_table[x-1].noflowpackets; # endif #else /* Unix */ retval = iface_info(x,IFACE_LOST); #endif return (u_char *)&retval; case CISTATUS: *write_method = &set_RowStatus; *var_len = sizeof(ci[x-1].ci_Status); return (u_char *)&ci[x-1].ci_Status; case CITIMEOUT: *write_method = &set_Integer; *var_len = sizeof(ci[x-1].ci_Timeout); return (u_char *)&ci[x-1].ci_Timeout; case CIOWNER: *write_method = &set_Name; *var_len = strlen(ci[x-1].ci_Owner); return (u_char *)ci[x-1].ci_Owner; case CILASTTIME: *write_method = &set_LastTime; *var_len = sizeof(ci[x-1].ci_LastTime); return (u_char *)&ci[x-1].ci_LastTime; case CIPREVTIME: *var_len = sizeof(ci[x-1].ci_PrevTime); return (u_char *)&ci[x-1].ci_PrevTime; case CIRULESET: *write_method = &set_ReaderSet; *var_len = sizeof(ci[x-1].ci_RuleSet); return (u_char *)&ci[x-1].ci_RuleSet; case CIMINPDUS: /* For nifty */ *write_method = &set_Integer; *var_len = sizeof(ci[x-1].ci_MinPDUs); return (u_char *)&ci[x-1].ci_MinPDUs; case CITIMEMARK: *write_method = &set_Integer; *var_len = sizeof(ci[x-1].ci_TimeMark); return (u_char *)&ci[x-1].ci_TimeMark; case MISTATUS: *write_method = &set_RowStatus; *var_len = sizeof(mi[x-1].mi_Status); return (u_char *)&mi[x-1].mi_Status; case MICURRENTRULESET: *write_method = &set_RuleSet; *var_len = sizeof(mi[x-1].mi_CurrentRuleSet); return (u_char *)&mi[x-1].mi_CurrentRuleSet; case MISTANDBYRULESET: *write_method = &set_RuleSet; *var_len = sizeof(mi[x-1].mi_StandbyRuleSet); return (u_char *)&mi[x-1].mi_StandbyRuleSet; case MIHIGHWATERMARK: *write_method = &set_Integer; *var_len = sizeof(mi[x-1].mi_HighWaterMark); return (u_char *)&mi[x-1].mi_HighWaterMark; case MIOWNER: *write_method = &set_Name; *var_len = strlen(mi[x-1].mi_Owner); return (u_char *)mi[x-1].mi_Owner; case MITIMESTAMP: *var_len = sizeof(mi[x-1].mi_TimeStamp); return (u_char *)&mi[x-1].mi_TimeStamp; case MIRUNNINGSTANDBY: *write_method = &set_RuleSet; *var_len = sizeof(mi[x-1].mi_RunningStandby); return (u_char *)&mi[x-1].mi_RunningStandby; default: *var_len = 0; ERROR(""); } return NULL; } #if NEW_ATR Bit8 *asn_build_distribution(Bit8 *data, int *seq_len, struct flow huge *f, int attrib) { Bit8 *save_data, nul; int j, a, var_len, dummy_len; struct distribution *d; int nb; /* Variables to handle dynamic distributions */ Bit8 *mask_r, *value_r; Bit8 mask_b[DISTRIB_PARAM_LEN], value_b[DISTRIB_PARAM_LEN]; save_data = data; data += 4; *seq_len -= 4; /* asn_build_sequence() always takes 4 bytes */ if ((f->distrib_bits & (1 << attrib-FTTOPACKETSIZE)) == 0) { nul = '\0'; /* Flow isn't building this distribution */ data = asn_build_string(data, seq_len, ASN_OCTET_STR, (u_char *)&nul, 1); } else { for (d = f->distrib_list; d != NULL; d = d->next) { if (d->selector == attrib) break; } if (d == NULL) { log_msg(LOG_ERR, 0, "Couldn't find distribution <<"); return NULL; } if (d->non_empty) { #if STR_DIST_DEBUG if (attrib == FTFLOWTIME) { if (f->stdata == NULL) log_msg(LOG_WARNING, 0, "build_dist(): f->stdata==NULL," " flownbr=%lu, flowruleset=%u, flowkind=%u", flow_nbr(f), f->FlowRuleSet, f->fk.FlowKind); } #endif if (d->Transform == DS_DYN_REQ) { nb = d->n_values; if (d->n_values > d->Buckets) { /* Distribution */ mask_b[0] = DS_DYN_BKT; mask_b[1] = d->ScaleFactor; mask_b[2] = d->LowerLimit >> 8; mask_b[3] = d->LowerLimit & 0xFF; mask_b[4] = d->UpperLimit >> 8; mask_b[5] = d->UpperLimit & 0xFF; mask_r = mask_b; value_r = d->value_params;; } else { /* Actual values */ memcpy(mask_b, d->mask_params, DISTRIB_PARAM_LEN); mask_b[0] = DS_DYN_PTS; memcpy(value_b, d->value_params, DISTRIB_PARAM_LEN); value_b[0] = nb; mask_r = mask_b; value_r = value_b; } d->non_empty = d->n_values = 0; /* Reset distrib values */ d->max_val = d->lowerlim; d->min_val = d->upperlim; } else { /* Linear or log */ nb = d->Buckets+1; mask_r = d->mask_params; value_r = d->value_params; } data = asn_build_string(data, seq_len, ASN_OCTET_STR, (u_char *)mask_r, DISTRIB_PARAM_LEN); if (data == NULL) return NULL; data = asn_build_string(data, seq_len, ASN_OCTET_STR, (u_char *)value_r, DISTRIB_PARAM_LEN); if (data == NULL) return NULL; for (j = 0; j != nb; ++j) { data = asn_build_int(data, seq_len, ASN_INTEGER, (Bit32 *)&d->counts[j], sizeof(Bit32)); if (data == NULL) return NULL; } } else { /* No counts in this distribution */ nul = '\0'; data = asn_build_string(data, seq_len, ASN_OCTET_STR, (u_char *)&nul, 1); } } var_len = data-save_data; dummy_len = 100; asn_build_sequence(save_data, &dummy_len, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), var_len-4); #if DST_TESTING for (j = 0; j != var_len; ++j) printf(" %02x", save_data[j]); printf("\n"); #endif return data; } Bit8 *asn_build_tcp_data(Bit8 *data, int *seq_len, struct flow huge *f) { Bit8 *save_data; Bit32 zero; int j, a, var_len, dummy_len; struct stream_data *std; save_data = data; data += 4; *seq_len -= 4; /* asn_build_sequence() always takes 4 bytes */ if ((std = f->stdata) == NULL) { zero = 0; /* Flow doesn't have stream data */ data = asn_build_int(data, seq_len, ASN_INTEGER, &zero, sizeof(Bit32)); } else { data = asn_build_int(data, seq_len, ASN_INTEGER, &std->n_streams, sizeof(Bit32)); if (data == NULL) return NULL; data = asn_build_int(data, seq_len, ASN_INTEGER, &std->mx_active_streams, sizeof(Bit32)); if (data == NULL) return NULL; data = asn_build_unsigned_int64(data, seq_len, COUNTER64, &std->ToTCPLenOctets, sizeof(counter64)); if (data == NULL) return NULL; data = asn_build_unsigned_int64(data, seq_len, COUNTER64, &std->FromTCPLenOctets, sizeof(counter64)); if (data == NULL) return NULL; data = asn_build_unsigned_int64(data, seq_len, COUNTER64, &std->ToTCPSeqOctets, sizeof(counter64)); if (data == NULL) return NULL; data = asn_build_unsigned_int64(data, seq_len, COUNTER64, &std->FromTCPSeqOctets, sizeof(counter64)); if (data == NULL) return NULL; data = asn_build_unsigned_int64(data, seq_len, COUNTER64, &std->ToTCPAckOctets, sizeof(counter64)); if (data == NULL) return NULL; data = asn_build_unsigned_int64(data, seq_len, COUNTER64, &std->FromTCPAckOctets, sizeof(counter64)); if (data == NULL) return NULL; data = asn_build_int(data, seq_len, ASN_INTEGER, &std->ToTCPDecrSeq, sizeof(Bit32)); if (data == NULL) return NULL; data = asn_build_int(data, seq_len, ASN_INTEGER, &std->FromTCPDecrSeq, sizeof(Bit32)); if (data == NULL) return NULL; } var_len = data-save_data; dummy_len = 100; asn_build_sequence(save_data, &dummy_len, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), var_len-4); #if TCP_TESTING for (j = 0; j != var_len; ++j) printf(" %02x", save_data[j]); printf("\n"); #endif return data; } #endif /* NEW_ATR */ Bit8 seq_buf[1500]; /* For data package return (must be global) */ u_char *var_ft( /* Flow Table */ struct variable *vp,oid *name, int *length, int exact, int *var_len, write_fn_type *write_method) { int rs; /* Flow ruleset */ Bit32 t_time; /* Flow 'target' time */ Bit32 x; /* Flow index */ struct flow huge *t; int pal; #if NEW_ATR int distr_len; Bit8 *bd_result; int tcp_len; Bit8 *tcp_result; #endif /* NEW_ATR */ struct rdr_rec *cip; /* For nifty */ int min_pdus; #ifdef TESTING int j; #endif rs = (int)name[11]; t_time = (Bit32)name[12]; x = (Bit32)name[13]; #ifdef TESTING scpos(0,scr_lrow); printf("var_ft(1): exact=%d, name=", exact); for (j = 0; j != *length; ++j) printf(".%d",name[j]); printf("\n"); #endif if (exact) { if (*length < 14) return NULL; /* 7 + 4 + 3 */ if (compare(newname,11, name,11) != 0 /* No match on OID */ || (t = find_flow(x)) == NULL /* Doesn't exist */ || t->FlowRuleSet != rs) /* Not in the reqd ruleset */ return NULL; } else { /* Does oid match up to indexes? */ if (compare(name,11, newname,11) != 0 || /* OID < flow attribute */ *length < 12) { /* No indeces given */ rs = 1; t_time = 0; x = 0; } else { if (*length == 12) { /* Ruleset given */ t_time = 0; x = 0; } else if (*length == 13) /* Ruleset and time value given */ x = 0; } for ( ; ; ++rs, x = 0) { if (rs > MXRTBLS) return NULL; if (ri[rs-1].ri_FlowRecords == 0) continue; /* No flows in table */ min_pdus = 0; /* Find MinPDUs for this reader (for nifty) */ for (cip = rs_rdr[rs-1]; cip != NULL; cip = cip->ci_rs_next) { if (cip->ci_TimeMark == t_time) { min_pdus = cip->ci_MinPDUs; break; } } if (x == 0) { x = ri[rs-1].ri_flow_chain; /* Test first flow of rs */ } else { t = find_flow(x); if (t->FlowRuleSet == rs) /* Test next flow of rs */ x = t->rs_next; else { /* Linear search */ for (++x; x <= mxflows; ++x) { t = find_flow(x); if (flow_idle(x)) /* Ignore deallocated flows */ continue; if (t->FlowRuleSet == rs) break; /* Found the next flow of rs */ } if (x > mxflows) x = 0; } } for (;;) { if (x == 0) break; /* No more flows for this rs */ t = &fa[x-1]; if (scmp32_ge(t->ntm_LastTime, t_time)) { /* Was >, but TimeFilter requires >=. Nevil, 10 Mar 98 */ /* Force signed copy to handle Bit32 wraparound */ if (min_pdus == 0 || ( c64geint(t->UpOctets, min_pdus) || /* For nifty */ c64geint(t->DownOctets, min_pdus) ) ) break; /* Active at or since target time */ } x = t->rs_next; } if (x != 0) break; } } newname[11] = (oid)rs; newname[12] = (oid)t_time; newname[13] = (oid)x; memcpy((u_char *)name, (u_char *)newname, ((int)vp->namelen+3)*sizeof(oid)); *length = (int)vp->namelen+3; *write_method = 0; *var_len = sizeof(retval); pal = addr_len[t->fk.PeerAddrType]; #ifdef TESTING scpos(0,scr_lrow); printf("var_ft(2): x=%d, t=%Fp, pal=%d, lowpeer=", x,t,pal); for (j = 0; j != 4; ++j) printf(".%d",t->fk.Low.PeerAddress[j]); printf("\n"); #endif switch (vp->magic) { case FTFLOWSTATUS: retval = 2; /* current(2) */ return (u_char *)&retval; case FTLOWINTERFACE: *var_len = sizeof(Bit8); return (u_char *)&t->fk.Low.Interface; case FTHIINTERFACE: *var_len = sizeof(Bit8); return (u_char *)&t->fk.High.Interface; case FTLOWADJACENTTYPE: *var_len = sizeof(Bit8); return (u_char *)&t->fk.Low.AdjAddrType; case FTHIADJACENTTYPE: *var_len = sizeof(Bit8); return (u_char *)&t->fk.High.AdjAddrType; case FTLOWADJACENTADDRESS: *var_len = MAC_ADDR_LEN; return (u_char *)&t->fk.Low.AdjAddr_ms4; case FTLOWADJACENTMASK: *var_len = MAC_ADDR_LEN; return (u_char *)&Masks[t->fk.Low.AdjMaskVal].Val; case FTLOWPEERTYPE: case FTHIPEERTYPE: *var_len = sizeof(Bit8); return (u_char *)&t->fk.PeerAddrType; case FTLOWPEERADDRESS: *var_len = pal; return (u_char *)&t->fk.Low.PeerAddress; case FTLOWPEERMASK: *var_len = pal; return (u_char *)&Masks[t->fk.Low.PeerMaskVal].Val; case FTLOWTRANSTYPE: case FTHITRANSTYPE: *var_len = sizeof(Bit8); return (u_char *)&t->fk.TransAddrType; case FTLOWTRANSADDRESS: *var_len = TRANS_ADDR_LEN; return (u_char *)&t->fk.Low.TransAddress; case FTLOWTRANSMASK: *var_len = TRANS_ADDR_LEN; return (u_char *)&Masks[t->fk.Low.TransMaskVal].Val; case FTHIADJACENTADDRESS: *var_len = MAC_ADDR_LEN; return (u_char *)&t->fk.High.AdjAddr_ms4; case FTHIADJACENTMASK: *var_len = MAC_ADDR_LEN; return (u_char *)&Masks[t->fk.High.AdjMaskVal].Val; case FTHIPEERADDRESS: *var_len = pal; return (u_char *)&t->fk.High.PeerAddress; case FTHIPEERMASK: *var_len = pal; return (u_char *)&Masks[t->fk.High.PeerMaskVal].Val; case FTHITRANSADDRESS: *var_len = TRANS_ADDR_LEN; return (u_char *)&t->fk.High.TransAddress; case FTHITRANSMASK: *var_len = TRANS_ADDR_LEN; return (u_char *)&Masks[t->fk.High.TransMaskVal].Val; case FTUPOCTETS: *var_len = sizeof(counter64); return (u_char *)&t->UpOctets; case FTUPPDUS: *var_len = sizeof(counter64); return (u_char *)&t->UpPDUs; case FTDOWNOCTETS: *var_len = sizeof(counter64); return (u_char *)&t->DownOctets; case FTDOWNPDUS: *var_len = sizeof(counter64); return (u_char *)&t->DownPDUs; case FTFIRSTTIME: return (u_char *)&t->FirstTime; case FTLASTTIME: return (u_char *)&t->LastTime; case FTSOURCECLASS: *var_len = sizeof(Bit8); return (u_char *)&t->fk.Low.Class; case FTDESTCLASS: *var_len = sizeof(Bit8); return (u_char *)&t->fk.High.Class; case FTFLOWCLASS: *var_len = sizeof(Bit8); return (u_char *)&t->fk.FlowClass; case FTSOURCEKIND: *var_len = sizeof(Bit8); return (u_char *)&t->fk.Low.Kind; case FTDESTKIND: *var_len = sizeof(Bit8); return (u_char *)&t->fk.High.Kind; case FTFLOWKIND: *var_len = sizeof(Bit8); return (u_char *)&t->fk.FlowKind; case FTDSCODEPOINT: *var_len = sizeof(Bit8); return (u_char *)&t->fk.DSCodePoint; #if NF_ASN_ATT case FTLOWROUTEASN: *var_len = TRANS_ADDR_LEN; return (u_char *)&t->fk.Low.RouteASN; case FTHIROUTEASN: *var_len = TRANS_ADDR_LEN; return (u_char *)&t->fk.High.RouteASN; case FTLOWROUTEPREFIX: *var_len = sizeof(Bit8); return (u_char *)&t->fk.Low.RoutePrefix; case FTHIROUTEPREFIX: *var_len = sizeof(Bit8); return (u_char *)&t->fk.High.RoutePrefix; #endif #if NF_OTHER_ATT case FTMETERID: *var_len = sizeof(Bit8); return (u_char *)&t->fk.MeterId; #endif #if NEW_ATR case FTDISTRIBUTIONS: *var_len = sizeof(Bit32); return (u_char *)&t->distrib_bits; case FTTOPACKETSIZE: case FTFROMPACKETSIZE: case FTTOINTERARRIVALTIME: case FTFROMINTERARRIVALTIME: case FTTOBITRATE: case FTFROMBITRATE: case FTTOPDURATE: case FTFROMPDURATE: case FTTOTURNAROUNDTIME1: case FTFROMTURNAROUNDTIME1: case FTTOTURNAROUNDTIME2: case FTFROMTURNAROUNDTIME2: case FTTOTURNAROUNDTIME3: case FTFROMTURNAROUNDTIME3: case FTTOTURNAROUNDTIME4: case FTFROMTURNAROUNDTIME4: case FTTOTCPSIZE: case FTFROMTCPSIZE: case FTTOTCPTIME: case FTFROMTCPTIME: case FTTOTCPRATE1: case FTFROMTCPRATE1: case FTTOTCPRATE2: case FTFROMTCPRATE2: case FTTOFLOWOCTETS: case FTFROMFLOWOCTETS: case FTTOFLOWPDUS: case FTFROMFLOWPDUS: case FTFLOWTIME: distr_len = sizeof(seq_buf)-100; bd_result = asn_build_distribution(seq_buf, &distr_len, t, vp->magic); *var_len = sizeof(seq_buf)-100 - distr_len; if (bd_result == NULL) return NULL; else return (u_char *)seq_buf; #endif /* NEW_ATR */ #if NEW_ATR case FTTOLOSTPDUS: retval = t->stdata != NULL ? t->stdata->ToLostPDUs : 0; return (u_char *)&retval; case FTFROMLOSTPDUS: retval = t->stdata != NULL ? t->stdata->FromLostPDUs : 0; return (u_char *)&retval; case FTTOPQOVERFLOWS: /* PQOF */ retval = t->stdata != NULL ? t->stdata->ToPQOverflows : 0; return (u_char *)&retval; case FTFROMPQOVERFLOWS: retval = t->stdata != NULL ? t->stdata->FromPQOverflows : 0; return (u_char *)&retval; case FTTCPDATA: tcp_len = sizeof(seq_buf)-100; tcp_result = asn_build_tcp_data(seq_buf, &tcp_len, t); *var_len = sizeof(seq_buf)-100 - tcp_len; if (tcp_result == NULL) return NULL; else return (u_char *)seq_buf; #endif /* NEW_ATR */ default: *var_len = 0; ERROR(""); } return NULL; } Bit32 last_t_time = 0; /* <> */ u_char *var_package( /* Data Package table */ struct variable *vp, oid *name, int *length, int exact, int *var_len, write_fn_type *write_method) { Bit8 attribs[MAX_NAME_LEN]; /* 'Selector' index */ int a_len, j,k, pal, seq_len, dummy_len; int rs; /* Flow ruleset */ Bit32 t_time; /* Flow 'target' time */ Bit32 x; /* Flow index */ struct flow huge *t; struct rdr_rec *cip; /* For nifty */ int min_pdus; Bit8 *data; int x0, nt; #ifdef PKTESTING scpos(0,scr_lrow); printf("var_package(1): exact=%d, name=", exact); for (j = 0; j != *length; ++j) printf(".%d",name[j]); printf("\n"); #endif if (*length < 13) return NULL; /* 7 + 4 + 2 */ /* Must have a selector with at least one attribute requested */ a_len = (int)name[11]; if (*length < 11+1+a_len) return NULL; /* Bad selector length */ newname[11] = (oid)a_len; for (j = 0, k = 12; j != a_len; ++j, ++k) { attribs[j] = (Bit8)name[k]; newname[k] = (oid)attribs[j]; } rs = (int)name[k]; t_time = (Bit32)name[k+1]; x = (Bit32)name[k+2]; #ifdef PKTESTING printf("%d attribs =", a_len); for (j = 0; j != a_len; ++j) printf(" %u", attribs[j]); printf("\nrs=%u, t_time=%d(%d), x=%u\n", rs,t_time,sizeof(t_time),x); #endif if (exact) { if (*length != k+3) return NULL; if (compare(newname,11, name,11) != 0 /* No match on OID */ || (t = find_flow(x)) == NULL /* Doesn't exist */ || t->FlowRuleSet != rs) /* Not in the reqd ruleset */ return NULL; } else { /* Does oid match up to indexes? */ if (compare(name,11, newname,11) != 0 || /* OID < flow attribute */ *length < k+1) { /* No indeces given */ rs = 1; t_time = 0; x = 0; } else { if (*length == k+1) { /* Ruleset given */ t_time = 0; x = 0; } else if (*length == k+2) /* Ruleset and time value given */ x = 0; } for ( ; ; ++rs, x = 0) { if (rs > MXRTBLS) return NULL; if (ri[rs-1].ri_FlowRecords == 0) continue; /* No flows in table */ min_pdus = 0; /* Find MinPDUs for this reader (for nifty) */ for (cip = rs_rdr[rs-1]; cip != NULL; cip = cip->ci_rs_next) { if (cip->ci_TimeMark == t_time) { min_pdus = cip->ci_MinPDUs; break; } } x0 = x; nt = 0; if (x == 0) { x = ri[rs-1].ri_flow_chain; /* Test first flow of rs */ } else { t = find_flow(x); if (t->FlowRuleSet == rs) /* Test next flow of rs */ x = t->rs_next; else { /* Linear search */ for (++x; x <= mxflows; ++x) { t = find_flow(x); if (flow_idle(x)) /* Ignore deallocated flows */ continue; if (t->FlowRuleSet == rs) break; /* Found the next flow of rs */ } if (x > mxflows) x = 0; } } for (;;) { if (x == 0) break; /* No more flows for this rs */ t = find_flow(x); if (t == NULL) { log_msg(LOG_ERR, 0, "ri[%d]: Couldn't find flow %lu !!!", rs, x); x = 0; /* Assume no more flows for this ruleset */ break; } ++nt; if (scmp32_ge(t->ntm_LastTime, t_time)) { /* Was >, but TimeFilter requires >=. Nevil, 10 Mar 98 */ /* Force signed copy to handle Bit32 wraparound */ if (min_pdus == 0 || ( c64geint(t->UpPDUs, min_pdus) || /* For nifty */ c64geint(t->DownPDUs, min_pdus) ) ) break; /* Active at or since target time */ } x = t->rs_next; } if (x != 0) { if ((x0 = x-x0) > rsc_mx_range) rsc_mx_range = x0; rsc_av_range += x0; if (nt > rsc_mx_tests) rsc_mx_tests = nt; rsc_av_tests += nt; ++rsc_n_searches; break; /* Break outer loop (flow is in this ruleset) */ } } } newname[k] = (oid)rs; newname[k+1] = (oid)t_time; newname[k+2] = (oid)x; memcpy((u_char *)name, (u_char *)newname, (k+3)*sizeof(oid)); *length = (int)k+3; pal = addr_len[t->fk.PeerAddrType]; switch (vp->magic) { case PTPACKAGE: data = seq_buf; seq_len = sizeof(seq_buf)-100; /* Leave room for header etc! */ data += 4; seq_len -= 4; /* asn_build_sequence() always takes 4 bytes */ for (j = 0; j != a_len; ++j) { switch (attribs[j]) { case FTFLOWSTATUS: retval = 2; /* current(2) */ data = asn_build_int(data, &seq_len, ASN_INTEGER, &retval, sizeof(retval)); break; case FTLOWINTERFACE: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.Low.Interface, sizeof(Bit8)); break; case FTHIINTERFACE: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.High.Interface, sizeof(Bit8)); break; case FTLOWADJACENTTYPE: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.Low.AdjAddrType, sizeof(Bit8)); break; case FTHIADJACENTTYPE: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.High.AdjAddrType, sizeof(Bit8)); break; case FTLOWADJACENTADDRESS: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&t->fk.Low.AdjAddr_ms4, MAC_ADDR_LEN); break; case FTLOWADJACENTMASK: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&Masks[t->fk.Low.AdjMaskVal].Val, MAC_ADDR_LEN); break; case FTLOWPEERTYPE: case FTHIPEERTYPE: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.PeerAddrType, sizeof(Bit8)); break; case FTLOWPEERADDRESS: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&t->fk.Low.PeerAddress, pal); break; case FTLOWPEERMASK: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&Masks[t->fk.Low.PeerMaskVal].Val, pal); break; case FTLOWTRANSTYPE: case FTHITRANSTYPE: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.TransAddrType, sizeof(Bit8)); break; case FTLOWTRANSADDRESS: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&t->fk.Low.TransAddress, TRANS_ADDR_LEN); break; case FTLOWTRANSMASK: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&Masks[t->fk.Low.TransMaskVal].Val, TRANS_ADDR_LEN); break; case FTHIADJACENTADDRESS: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&t->fk.High.AdjAddr_ms4, MAC_ADDR_LEN); break; case FTHIADJACENTMASK: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&Masks[t->fk.High.AdjMaskVal].Val, MAC_ADDR_LEN); break; case FTHIPEERADDRESS: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&t->fk.High.PeerAddress, pal); break; case FTHIPEERMASK: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&Masks[t->fk.High.PeerMaskVal].Val, pal); break; case FTHITRANSADDRESS: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&t->fk.High.TransAddress, TRANS_ADDR_LEN); break; case FTHITRANSMASK: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&Masks[t->fk.High.TransMaskVal].Val, TRANS_ADDR_LEN); break; case FTRULESET: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->FlowRuleSet, sizeof(Bit8)); break; case FTUPOCTETS: data = asn_build_unsigned_int64(data, &seq_len, COUNTER64, &t->UpOctets, sizeof(counter64)); break; case FTUPPDUS: data = asn_build_unsigned_int64(data, &seq_len, COUNTER64, &t->UpPDUs, sizeof(counter64)); break; case FTDOWNOCTETS: data = asn_build_unsigned_int64(data, &seq_len, COUNTER64, &t->DownOctets, sizeof(counter64)); break; case FTDOWNPDUS: data = asn_build_unsigned_int64(data, &seq_len, COUNTER64, &t->DownPDUs, sizeof(counter64)); break; case FTFIRSTTIME: data = asn_build_int(data, &seq_len, TIMETICKS, &t->FirstTime, sizeof(Bit32)); break; case FTLASTTIME: data = asn_build_int(data, &seq_len, TIMETICKS, &t->LastTime, sizeof(Bit32)); break; case FTSOURCECLASS: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.Low.Class, sizeof(Bit8)); break; case FTDESTCLASS: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.High.Class, sizeof(Bit8)); break; case FTFLOWCLASS: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.FlowClass, sizeof(Bit8)); break; case FTSOURCEKIND: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.Low.Kind, sizeof(Bit8)); break; case FTDESTKIND: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.High.Kind, sizeof(Bit8)); break; case FTFLOWKIND: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.FlowKind, sizeof(Bit8)); break; case FTDSCODEPOINT: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.DSCodePoint, sizeof(Bit8)); break; #if NF_ASN_ATT case FTLOWROUTEASN: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&t->fk.Low.RouteASN, TRANS_ADDR_LEN); break; case FTHIROUTEASN: data = asn_build_string(data, &seq_len, ASN_OCTET_STR, (u_char *)&t->fk.High.RouteASN, TRANS_ADDR_LEN); break; case FTLOWROUTEPREFIX: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.Low.RoutePrefix, sizeof(Bit8)); break; case FTHIROUTEPREFIX: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.High.RoutePrefix, sizeof(Bit8)); break; #endif #if NF_OTHER_ATT case FTMETERID: data = asn_build_int(data, &seq_len, ASN_INTEGER, (Bit32 *)&t->fk.MeterId, sizeof(Bit8)); break; #endif #if NEW_ATR case FTDISTRIBUTIONS: data = asn_build_unsigned_int(data, &seq_len, UINTEGER, (Bit32 *)&t->distrib_bits, sizeof(Bit32)); break; case FTTOPACKETSIZE: case FTFROMPACKETSIZE: case FTTOINTERARRIVALTIME: case FTFROMINTERARRIVALTIME: case FTTOBITRATE: case FTFROMBITRATE: case FTTOPDURATE: case FTFROMPDURATE: case FTTOTURNAROUNDTIME1: case FTFROMTURNAROUNDTIME1: case FTTOTURNAROUNDTIME2: case FTFROMTURNAROUNDTIME2: case FTTOTURNAROUNDTIME3: case FTFROMTURNAROUNDTIME3: case FTTOTURNAROUNDTIME4: case FTFROMTURNAROUNDTIME4: case FTTOTCPSIZE: case FTFROMTCPSIZE: case FTTOTCPTIME: case FTFROMTCPTIME: case FTTOTCPRATE1: case FTFROMTCPRATE1: case FTTOTCPRATE2: case FTFROMTCPRATE2: case FTTOFLOWOCTETS: case FTFROMFLOWOCTETS: case FTTOFLOWPDUS: case FTFROMFLOWPDUS: case FTFLOWTIME: data = asn_build_distribution(data, &seq_len, t, attribs[j]); break; case FTTOLOSTPDUS: retval = t->stdata != NULL ? t->stdata->ToLostPDUs : 0; data = asn_build_int(data, &seq_len, ASN_INTEGER, &retval, sizeof(retval)); break; case FTFROMLOSTPDUS: retval = t->stdata != NULL ? t->stdata->FromLostPDUs : 0; data = asn_build_int(data, &seq_len, ASN_INTEGER, &retval, sizeof(retval)); break; case FTTOPQOVERFLOWS: /* PQOF */ retval = t->stdata != NULL ? t->stdata->ToPQOverflows : 0; data = asn_build_int(data, &seq_len, ASN_INTEGER, &retval, sizeof(retval)); break; case FTFROMPQOVERFLOWS: retval = t->stdata != NULL ? t->stdata->FromPQOverflows : 0; data = asn_build_int(data, &seq_len, ASN_INTEGER, &retval, sizeof(retval)); break; case FTTCPDATA: data = asn_build_tcp_data(data, &seq_len, t); break; #endif /* NEW_ATR */ default: ERROR(""); data = asn_build_null(data, &seq_len, ASN_NULL); } if (data == NULL) { /* Package too big! */ *var_len = 1; /* TOOBIG rather than ENDOFMIB */ return NULL; } } *var_len = data-seq_buf; data = seq_buf; dummy_len = sizeof(seq_buf); asn_build_sequence(data, &dummy_len, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), *var_len-4); #ifdef PKTESTING for (j = 0; j != *var_len; ++j) printf(" %02x", seq_buf[j]); printf("\n"); #endif return (u_char *)seq_buf; default: *length = 0; ERROR(""); } return NULL; } u_char *var_rt( /* Rule table */ struct variable *vp, oid *name, int *length, int exact, int *var_len, write_fn_type *write_method) { int rule_set; Bit16 x, sz; struct rule huge *r, huge *rt; #ifdef RTTESTING int j, cmp; rule_set = (int)name[11]; x = (Bit16)name[12]; scpos(0,scr_lrow); printf("var_rt(): exact=%d, set=%d, x=%d\n name=", exact,rule_set,x); for (j = 0; j != *length; ++j) printf(".%d",name[j]); printf("\n"); #endif if (exact) { if (*length < 13) return NULL; if ((rule_set = (int)name[11]) < 1 || rule_set > MXRTBLS) return NULL; x = (Bit16)name[12]; if ((rt = ri[rule_set-1].ri_rule_table) == NULL) return NULL; if (x > (sz = ri[rule_set-1].ri_Size)) return NULL; newname[11] = (oid)rule_set; newname[12] = (oid)x; if (compare(newname,(int)vp->namelen+2, name,*length) != 0) return NULL; if ((r = &rt[x-1]) == NULL) return NULL; } else { /* Does oid match up to indexes? */ if (compare(name,11, newname,11) != 0 || *length < 13) { /* No: find first entry */ rule_set = 1; x = 0; /* Have to search whole 2-D rule table */ } else { if ((rule_set = name[11]) < 1 || rule_set > MXRTBLS) return NULL; x = (Bit16)name[12]; } for ( ; ; ++rule_set, x = 0) { if (rule_set > MXRTBLS) return NULL; if ((rt = ri[rule_set-1].ri_rule_table) == NULL) continue; if (x >= (sz = ri[rule_set-1].ri_Size)) continue; newname[11] = (oid)rule_set; for (++x; x <= sz; ++x) { if ((r = &rt[x-1]) == NULL) continue; newname[12] = (oid)x; #ifdef RTTESTING cmp = compare(newname,(int)vp->namelen+2, name,*length); printf("x=%d, cmp=%d ", x,cmp); for (j = 0; j != (int)vp->namelen+2; ++j) printf(".%d",newname[j]); printf("\n"); if (cmp > 0) break; #else if (compare(newname,(int)vp->namelen+2, name,*length) > 0) break; #endif } if (x <= sz) break; /* Found the next one! */ } } memcpy((u_char *)name, (u_char *)newname, ((int)vp->namelen+2)*sizeof(oid)); *length = (int)vp->namelen+2; #ifdef RTTESTING #ifdef DOS printf(" rt[%d], address=%Fp, x=%d\n", rule_set, r, x); #else printf(" rt[%d], address=%lu, x=%d\n", rule_set, r, x); fflush(stdout); #endif #endif *write_method = 0; switch (vp->magic) { case RTSELECTOR: *var_len = sizeof(r->RuleSelector); return (u_char *)&r->RuleSelector; case RTRULEMASK: *write_method = &writeMask; *var_len = RULE_ADDR_LEN; return (u_char *)&Masks[r->RuleMaskVal].Val; case RTMATCHVALUE: *var_len = RULE_ADDR_LEN; return (u_char *)r->RuleMatchedValue.rule; case RTRULEACTION: *var_len = sizeof(r->RuleAction); return (u_char *)&r->RuleAction; case RTJUMPINDEX: *var_len = sizeof(r->RuleJumpIndex); *write_method = &set_Bit16; return (u_char *)&r->RuleJumpIndex; default: *var_len = 0; ERROR(""); } return NULL; }