home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / netramet / part15 < prev    next >
Encoding:
Text File  |  1993-11-07  |  63.8 KB  |  2,079 lines

  1. Newsgroups: comp.sources.misc
  2. From: nevil@ccu1.aukuni.ac.nz (J Nevil Brownlee)
  3. Subject: v40i103:  netramet - Network Traffic Accounting Meter, Part15/25
  4. Message-ID: <1993Nov7.221241.12270@sparky.sterling.com>
  5. X-Md4-Signature: 1d8cadb7370b889a7718f96273ed17ea
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sun, 7 Nov 1993 22:12:41 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: nevil@ccu1.aukuni.ac.nz (J Nevil Brownlee)
  12. Posting-number: Volume 40, Issue 103
  13. Archive-name: netramet/part15
  14. Environment: INET, UNIX, DOS
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  netramet/src/manager/nm.jul.c netramet/src/manager/nmc.c
  21. # Wrapped by kent@sparky on Tue Nov  2 18:17:09 1993
  22. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 15 (of 25)."'
  25. if test -f 'netramet/src/manager/nm.jul.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'netramet/src/manager/nm.jul.c'\"
  27. else
  28.   echo shar: Extracting \"'netramet/src/manager/nm.jul.c'\" \(43638 characters\)
  29.   sed "s/^X//" >'netramet/src/manager/nm.jul.c' <<'END_OF_FILE'
  30. X/* 1730, Fri 3 Sep 93
  31. X
  32. X   NM.C:  First attempt at a manager for the AU Accounting Meter
  33. X
  34. X   Copyright (C) 1992,1993 by Nevil Brownlee,
  35. X   Computer Centre,  University of Auckland */
  36. X
  37. X/***********************************************************
  38. X    Copyright 1988 by Carnegie Mellon University
  39. X
  40. X                      All Rights Reserved
  41. X
  42. XPermission to use, copy, modify, and distribute this software and its 
  43. Xdocumentation for any purpose and without fee is hereby granted, 
  44. Xprovided that the above copyright notice appear in all copies and that
  45. Xboth that copyright notice and this permission notice appear in 
  46. Xsupporting documentation, and that the name of CMU not be
  47. Xused in advertising or publicity pertaining to distribution of the
  48. Xsoftware without specific, written prior permission.  
  49. X
  50. XCMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  51. XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  52. XCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  53. XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  54. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  55. XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  56. XSOFTWARE.
  57. X******************************************************************/
  58. X#include <sys/param.h>
  59. X#include <sys/types.h>
  60. X#include <netinet/in.h>
  61. X#include <netdb.h>
  62. X
  63. X#include <stdio.h>
  64. X#include <ctype.h>
  65. X#include <sys/time.h>
  66. X#include <errno.h>
  67. X
  68. X#include <string.h>
  69. X#include <malloc.h>
  70. X
  71. X#include "snmp.h"
  72. X#include "snmpimpl.h"
  73. X#include "asn1.h"
  74. X#include "snmpclnt.h"
  75. X#include "snmpapi.h"
  76. X#include "mib.h"
  77. X
  78. X#ifndef BSD4_3
  79. X#define BSD4_2
  80. X#endif
  81. X
  82. X#define RULEFILE "rules.txt"
  83. X
  84. Xextern int  errno;
  85. Xint    snmp_dump_packet = 0;
  86. X
  87. X#define  INT_ACCT  1, 3, 6, 1, 3, 99
  88. X#define  AUKUNI    1, 3, 6, 1, 4, 1, 411
  89. X
  90. Xoid o_sysDescr[]      = {MIB, 1, 1, 0};
  91. Xoid o_sysUpTime[]      = {MIB, 1, 3, 0};
  92. Xoid o_ifNumber[]      = {MIB, 2, 1, 0};
  93. X
  94. Xoid o_InactivityTimeout[] = {INT_ACCT, 1,  3, 0};
  95. Xoid o_LastCollectTime[]   = {INT_ACCT, 1,  6, 0};
  96. Xoid o_riRuleSize[]        = {INT_ACCT, 1,  7, 1, 2, 0xFF};
  97. Xoid o_riActionSize[]      = {INT_ACCT, 1,  7, 1, 3, 0xFF};
  98. Xoid o_CurrentRuleSet[]    = {INT_ACCT, 1,  8, 0};
  99. Xoid o_EmergencyRuleSet[]  = {INT_ACCT, 1,  9, 0};
  100. X
  101. Xoid o_ftFlowIndex[]            = {INT_ACCT, 2, 1, 1,  1, 0xFFFF};
  102. Xoid o_ftFlowStatus[]           = {INT_ACCT, 2, 1, 1,  2, 0xFFFF};
  103. Xoid o_ftLowInterface[]         = {INT_ACCT, 2, 1, 1,  3, 0xFFFF};
  104. Xoid o_ftLowAdjacentType[]      = {INT_ACCT, 2, 1, 1,  4, 0xFFFF};
  105. Xoid o_ftLowAdjacentAddress[]   = {INT_ACCT, 2, 1, 1,  5, 0xFFFF};
  106. Xoid o_ftLowAdjacentMask[]      = {INT_ACCT, 2, 1, 1,  6, 0xFFFF};
  107. Xoid o_ftLowPeerType[]          = {INT_ACCT, 2, 1, 1,  7, 0xFFFF};
  108. Xoid o_ftLowPeerAddress[]       = {INT_ACCT, 2, 1, 1,  8, 0xFFFF};
  109. Xoid o_ftLowPeerMask[]          = {INT_ACCT, 2, 1, 1,  9, 0xFFFF};
  110. Xoid o_ftLowDetailType[]        = {INT_ACCT, 2, 1, 1, 10, 0xFFFF};
  111. Xoid o_ftLowDetailAddress[]     = {INT_ACCT, 2, 1, 1, 11, 0xFFFF};
  112. Xoid o_ftLowDetailMask[]        = {INT_ACCT, 2, 1, 1, 12, 0xFFFF};
  113. Xoid o_ftHighInterface[]        = {INT_ACCT, 2, 1, 1, 15, 0xFFFF};
  114. Xoid o_ftHighAdjacentType[]     = {INT_ACCT, 2, 1, 1, 16, 0xFFFF};
  115. Xoid o_ftHighAdjacentAddress[]  = {INT_ACCT, 2, 1, 1, 17, 0xFFFF};
  116. Xoid o_ftHighAdjacentMask[]     = {INT_ACCT, 2, 1, 1, 18, 0xFFFF};
  117. Xoid o_ftHighPeerType[]         = {INT_ACCT, 2, 1, 1, 19, 0xFFFF};
  118. Xoid o_ftHighPeerAddress[]      = {INT_ACCT, 2, 1, 1, 20, 0xFFFF};
  119. Xoid o_ftHighPeerMask[]         = {INT_ACCT, 2, 1, 1, 21, 0xFFFF};
  120. Xoid o_ftHighDetailType[]       = {INT_ACCT, 2, 1, 1, 22, 0xFFFF};
  121. Xoid o_ftHighDetailAddress[]    = {INT_ACCT, 2, 1, 1, 23, 0xFFFF};
  122. Xoid o_ftHighDetailMask[]       = {INT_ACCT, 2, 1, 1, 24, 0xFFFF};
  123. Xoid o_ftPDUScale[]             = {INT_ACCT, 2, 1, 1, 29, 0xFFFF};
  124. Xoid o_ftOctetScale[]           = {INT_ACCT, 2, 1, 1, 30, 0xFFFF};
  125. Xoid o_ftRuleSet[]              = {INT_ACCT, 2, 1, 1, 31, 0xFFFF};
  126. Xoid o_ftFlowType[]             = {INT_ACCT, 2, 1, 1, 32, 0xFFFF};
  127. Xoid o_ftUpOctets[]             = {INT_ACCT, 2, 1, 1, 33, 0xFFFF};
  128. Xoid o_ftUpPDUs[]               = {INT_ACCT, 2, 1, 1, 34, 0xFFFF};
  129. Xoid o_ftDownOctets[]           = {INT_ACCT, 2, 1, 1, 35, 0xFFFF};
  130. Xoid o_ftDownPDUs[]             = {INT_ACCT, 2, 1, 1, 36, 0xFFFF};
  131. Xoid o_ftFirstTime[]            = {INT_ACCT, 2, 1, 1, 37, 0xFFFF};
  132. Xoid o_ftLastTime[]             = {INT_ACCT, 2, 1, 1, 38, 0xFFFF};
  133. X
  134. Xoid o_ftCreateTime[]      = {INT_ACCT, 2, 2, 1, 1, 0xFFFFFFFF, 0xFFFF};
  135. Xoid o_ftCreateIndex[]      = {INT_ACCT, 2, 2, 1, 2, 0xFFFFFFFF, 0xFFFF};
  136. X
  137. Xoid o_ftActiveTime[]      = {INT_ACCT, 2, 3, 1, 1, 0xFFFFFFFF, 0xFFFF};
  138. Xoid o_ftActiveIndex[]      = {INT_ACCT, 2, 3, 1, 2, 0xFFFFFFFF, 0xFFFF};
  139. Xoid o_ftActiveFlowBlob[]  = {INT_ACCT, 2, 3, 1, 3, 0xFFFFFFFF, 0xFFFF};
  140. X
  141. Xoid o_rtSelector[]        = {INT_ACCT, 3, 1, 1, 3, 0xFF, 0xFFFF};
  142. Xoid o_rtRuleMask[]        = {INT_ACCT, 3, 1, 1, 4, 0xFF, 0xFFFF};
  143. Xoid o_rtMatchedValue[]    = {INT_ACCT, 3, 1, 1, 5, 0xFF, 0xFFFF};
  144. Xoid o_rtRuleAction[]      = {INT_ACCT, 3, 1, 1, 6, 0xFF, 0xFFFF};
  145. Xoid o_rtJumpIndex[]       = {INT_ACCT, 3, 1, 1, 7, 0xFF, 0xFFFF};
  146. X
  147. Xoid o_atLowInterface[]         = {INT_ACCT, 4, 1, 1,  3, 0xFF, 0xFFFF};
  148. Xoid o_atLowAdjacentType[]      = {INT_ACCT, 4, 1, 1,  4, 0xFF, 0xFFFF};
  149. Xoid o_atLowAdjacentAddress[]   = {INT_ACCT, 4, 1, 1,  5, 0xFF, 0xFFFF};
  150. Xoid o_atLowAdjacentMask[]      = {INT_ACCT, 4, 1, 1,  6, 0xFF, 0xFFFF};
  151. Xoid o_atLowPeerType[]          = {INT_ACCT, 4, 1, 1,  7, 0xFF, 0xFFFF};
  152. Xoid o_atLowPeerAddress[]       = {INT_ACCT, 4, 1, 1,  8, 0xFF, 0xFFFF};
  153. Xoid o_atLowPeerMask[]          = {INT_ACCT, 4, 1, 1,  9, 0xFF, 0xFFFF};
  154. Xoid o_atLowDetailType[]        = {INT_ACCT, 4, 1, 1, 10, 0xFF, 0xFFFF};
  155. Xoid o_atLowDetailAddress[]     = {INT_ACCT, 4, 1, 1, 11, 0xFF, 0xFFFF};
  156. Xoid o_atLowDetailMask[]        = {INT_ACCT, 4, 1, 1, 12, 0xFF, 0xFFFF};
  157. Xoid o_atHighInterface[]        = {INT_ACCT, 4, 1, 1, 15, 0xFF, 0xFFFF};
  158. Xoid o_atHighAdjacentType[]     = {INT_ACCT, 4, 1, 1, 16, 0xFF, 0xFFFF};
  159. Xoid o_atHighAdjacentAddress[]  = {INT_ACCT, 4, 1, 1, 17, 0xFF, 0xFFFF};
  160. Xoid o_atHighAdjacentMask[]     = {INT_ACCT, 4, 1, 1, 18, 0xFF, 0xFFFF};
  161. Xoid o_atHighPeerType[]         = {INT_ACCT, 4, 1, 1, 19, 0xFF, 0xFFFF};
  162. Xoid o_atHighPeerAddress[]      = {INT_ACCT, 4, 1, 1, 20, 0xFF, 0xFFFF};
  163. Xoid o_atHighPeerMask[]         = {INT_ACCT, 4, 1, 1, 21, 0xFF, 0xFFFF};
  164. Xoid o_atHighDetailType[]       = {INT_ACCT, 4, 1, 1, 22, 0xFF, 0xFFFF};
  165. Xoid o_atHighDetailAddress[]    = {INT_ACCT, 4, 1, 1, 23, 0xFF, 0xFFFF};
  166. Xoid o_atHighDetailMask[]       = {INT_ACCT, 4, 1, 1, 24, 0xFF, 0xFFFF};
  167. Xoid o_atPDUScale[]             = {INT_ACCT, 4, 1, 1, 29, 0xFF, 0xFFFF};
  168. Xoid o_atOctetScale[]           = {INT_ACCT, 4, 1, 1, 30, 0xFF, 0xFFFF};
  169. Xoid o_atRuleSet[]              = {INT_ACCT, 4, 1, 1, 31, 0xFF, 0xFFFF};
  170. X
  171. Xoid o_pcNearMem[]         = {AUKUNI, 2, 1, 0};
  172. Xoid o_pcFarMem[]          = {AUKUNI, 2, 2, 0};
  173. Xoid o_pcBadPackets[]      = {AUKUNI, 2, 3, 0};
  174. Xoid o_pcNoBufPackets[]    = {AUKUNI, 2, 4, 0};
  175. Xoid o_pcLostPackets[]     = {AUKUNI, 2, 5, 0};
  176. Xoid o_pcPacketBacklog[]   = {AUKUNI, 2, 6, 0};
  177. Xoid o_pcChkSearches[]     = {AUKUNI, 2, 7, 0};
  178. Xoid o_pcChkCompares[]     = {AUKUNI, 2, 8, 0};
  179. X
  180. X#define MAC_ADDR_LEN     6
  181. X#define PEER_ADDR_LEN    4
  182. X#define DETAIL_ADDR_LEN  2
  183. X
  184. X#define RULE_ADDR_LEN    6
  185. X
  186. Xstruct flow_info {
  187. X   unsigned char AdjAddrType,
  188. X      LowAdjAddress[MAC_ADDR_LEN], LowAdjMask[MAC_ADDR_LEN],
  189. X      HighAdjAddress[MAC_ADDR_LEN], HighAdjMask[MAC_ADDR_LEN];
  190. X   unsigned char PeerAddrType,
  191. X      LowPeerAddress[PEER_ADDR_LEN], LowPeerMask[PEER_ADDR_LEN],
  192. X      HighPeerAddress[PEER_ADDR_LEN], HighPeerMask[PEER_ADDR_LEN];
  193. X   unsigned char DetailAddrType,
  194. X      LowDetailAddress[DETAIL_ADDR_LEN], LowDetailMask[DETAIL_ADDR_LEN],
  195. X      HighDetailAddress[DETAIL_ADDR_LEN], HighDetailMask[DETAIL_ADDR_LEN];
  196. X   unsigned long
  197. X      FwdPackets,FwdBytes,  BackPackets,BackBytes,
  198. X      FirstTime,LastTime;
  199. X   };
  200. X
  201. Xstruct rule_info {
  202. X   int RuleSet, RuleNbr;
  203. X   unsigned char RuleSelector,
  204. X      RuleMask[RULE_ADDR_LEN], RuleMatchedValue[RULE_ADDR_LEN], 
  205. X      RuleAction, RuleJumpIndex;
  206. X   };
  207. X
  208. Xstruct action_info {
  209. X   int ActionSet, ActionNbr;
  210. X   unsigned char AdjAddrType,
  211. X      LowAdjAddress[MAC_ADDR_LEN], LowAdjMask[MAC_ADDR_LEN],
  212. X      HighAdjAddress[MAC_ADDR_LEN], HighAdjMask[MAC_ADDR_LEN];
  213. X   unsigned char PeerAddrType,
  214. X      LowPeerAddress[PEER_ADDR_LEN], LowPeerMask[PEER_ADDR_LEN],
  215. X      HighPeerAddress[PEER_ADDR_LEN], HighPeerMask[PEER_ADDR_LEN];
  216. X   unsigned char DetailAddrType,
  217. X      LowDetailAddress[DETAIL_ADDR_LEN], LowDetailMask[DETAIL_ADDR_LEN],
  218. X      HighDetailAddress[DETAIL_ADDR_LEN], HighDetailMask[DETAIL_ADDR_LEN];
  219. X   };
  220. X
  221. X#define AT_IGNORE     0  /* Addr_type values */
  222. X#define AT_IP         2
  223. X#define AT_NOVELL     6
  224. X#define AT_DECNET     5
  225. X#define AT_ETHERTALK  7
  226. X
  227. X#define RS_NULL           0
  228. X#define RS_LOWPEERTYPE    7
  229. X#define RS_LOWPEERADDR    8
  230. X#define RS_HIPEERADDR    20
  231. X
  232. X#define RA_COUNT      1
  233. X#define RA_TALLY      2
  234. X#define RA_AGGREGATE  3
  235. X#define RA_SUCCEED    4
  236. X#define RA_FAIL       5
  237. X#define RA_PUSHTO     6
  238. X#define RA_POPTO      7
  239. X#define RA_GOTO       8
  240. X
  241. X#define RF_SET       -1
  242. X#define RF_RULES     -2
  243. X#define RF_ACTIONS   -3
  244. X
  245. X#define FTFLOWINDEX        1  /* Flow table attribute values */
  246. X#define FTFLOWSTATUS        2
  247. X
  248. X#define FTLOWINTERFACE          3
  249. X#define FTLOWADJACENTTYPE       4
  250. X#define FTLOWADJACENTADDRESS    5
  251. X#define FTLOWADJACENTMASK       6
  252. X#define FTLOWPEERTYPE        7
  253. X#define FTLOWPEERADDRESS    8
  254. X#define FTLOWPEERMASK        9
  255. X#define FTLOWDETAILTYPE        10
  256. X#define FTLOWDETAILADDRESS     11
  257. X#define FTLOWDETAILMASK        12
  258. X#define FTLOWSUBSCRIBERID      13
  259. X#define FTLOWSUBSCRIBERMASK    14
  260. X#define FTHIINTERFACE          15
  261. X#define FTHIADJACENTTYPE       16
  262. X#define FTHIADJACENTADDRESS    17
  263. X#define FTHIADJACENTMASK       18
  264. X#define FTHIPEERTYPE           19
  265. X#define FTHIPEERADDRESS           20
  266. X#define FTHIPEERMASK           21
  267. X#define FTHIDETAILTYPE         22
  268. X#define FTHIDETAILADDRESS      23
  269. X#define FTHIDETAILMASK         24
  270. X#define FTHISUBSCRIBERID       25
  271. X#define FTHISUBSCRIBERMASK     26
  272. X
  273. X#define FTSUBSCRIBERID         27
  274. X#define FTSUBSCRIBERMASK       28
  275. X
  276. X#define FTPDUSCALE             29
  277. X#define FTOCTETSCALE           30
  278. X#define FTRULESET              31
  279. X#define FTFLOWTYPE             32
  280. X
  281. X#define FTUPOCTETS           33
  282. X#define FTUPPDUS           34
  283. X#define FTDOWNOCTETS           35
  284. X#define FTDOWNPDUS           36
  285. X
  286. X#define FTFIRSTTIME           37
  287. X#define FTLASTTIME           38
  288. X
  289. X#define ATN  1  /* Number.  Attribute type values */
  290. X#define ATA  2  /* Address */
  291. X#define ANI  0  /* Not implemented */
  292. X
  293. Xstruct attrib_info {
  294. X   unsigned char *name;
  295. X   unsigned char index;
  296. X   unsigned char type;
  297. X   unsigned char len;
  298. X   };
  299. X
  300. Xstruct attrib_info attribs[1+FTLASTTIME-FTFLOWINDEX] = {
  301. X   "flowindex",              FTFLOWINDEX,           ATN, 2,
  302. X   "flowstatus",             FTFLOWSTATUS,          ATN, 1,
  303. X   "sourceinterface",        FTLOWINTERFACE,        ATN, 1,
  304. X   "sourceadjacenttype",     FTLOWADJACENTTYPE,     ATN, 1,
  305. X   "sourceadjacentaddress",  FTLOWADJACENTADDRESS,  ATA, MAC_ADDR_LEN,
  306. X   "sourceadjacentmask",     FTLOWADJACENTMASK,     ATA, MAC_ADDR_LEN,
  307. X   "sourcepeertype",         FTLOWPEERTYPE,         ATN, 1,
  308. X   "sourcepeeraddress",      FTLOWPEERADDRESS,      ATA, PEER_ADDR_LEN,
  309. X   "sourcapeermask",         FTLOWPEERMASK,         ATA, PEER_ADDR_LEN,
  310. X   "sourcedetailtype",       FTLOWDETAILTYPE,       ATN, 1,
  311. X   "sourcedetailaddress",    FTLOWDETAILADDRESS,    ATA, DETAIL_ADDR_LEN,
  312. X   "sourcedetailmask",       FTLOWDETAILMASK,       ATA, DETAIL_ADDR_LEN,
  313. X   "sourcesubscriberid",     FTLOWSUBSCRIBERID,     ANI, 0,
  314. X   "sourcesubscribermask",   FTLOWSUBSCRIBERMASK,   ANI, 0,
  315. X   "destinterface",          FTHIINTERFACE,         ATN, 1,
  316. X   "destadjacenttype",       FTHIADJACENTTYPE,      ATN, 1,
  317. X   "destadjacentaddress",    FTHIADJACENTADDRESS,   ATA, MAC_ADDR_LEN,
  318. X   "destadjacentmask",       FTHIADJACENTMASK,      ATA, MAC_ADDR_LEN,
  319. X   "destpeertype",           FTHIPEERTYPE,          ATN, 1,
  320. X   "destpeeraddress",        FTHIPEERADDRESS,       ATA, PEER_ADDR_LEN,
  321. X   "sourcapeermask",         FTHIPEERMASK,          ATA, PEER_ADDR_LEN,
  322. X   "destdetailtype",         FTHIDETAILTYPE,        ATN, 1,
  323. X   "destdetailaddress",      FTHIDETAILADDRESS,     ATA, DETAIL_ADDR_LEN,
  324. X   "destdetailmask",         FTHIDETAILMASK,        ATA, DETAIL_ADDR_LEN,
  325. X   "destsubscriberid",       FTHISUBSCRIBERID,      ANI, 0,
  326. X   "destsubscribermask",     FTHISUBSCRIBERMASK,    ANI, 0,
  327. X   "subscriberid",           FTSUBSCRIBERID,        ANI, 0,
  328. X   "subscribermask",         FTSUBSCRIBERMASK,      ANI, 0,
  329. X   "pduscale",               FTPDUSCALE,            ANI, 0,
  330. X   "octetscale",             FTOCTETSCALE,          ANI, 0,
  331. X   "flowruleset",            FTRULESET,             ATN, 1,
  332. X   "flowtype",               FTFLOWTYPE,            ATN, 1,
  333. X   "tooctets",               FTUPOCTETS,            ATN, 4,
  334. X   "topdus",                 FTUPPDUS,              ATN, 4,
  335. X   "fromoctets",             FTDOWNOCTETS,          ATN, 4,
  336. X   "frompdus",               FTDOWNPDUS,            ATN, 4,
  337. X   "firsttime",              FTFIRSTTIME,           ATN, 4,
  338. X   "lasttime",               FTLASTTIME,            ATN, 4
  339. X   };
  340. X
  341. X#define FLOWBLOBSZ  25
  342. X
  343. Xunsigned char column_blob[
  344. X   (FLOWBLOBSZ+2)*(2+RULE_ADDR_LEN)];
  345. X
  346. X#ifdef AU_MSDOS  /* PC ntoh routines swap the byte order */
  347. X#define netshort(x)  x
  348. X#define netlong(x)   x
  349. X#else            /* SunOS ntoh routines don't */
  350. X#define netshort(x)  htons(x)
  351. X#define netlong(x)   htonl(x)
  352. X#endif
  353. X
  354. X#define NAME_LN  64
  355. X
  356. Xstruct meter_status {
  357. X   struct meter_status *next;
  358. X
  359. X   char name[NAME_LN];
  360. X   char community[NAME_LN];
  361. X   char rulefile[NAME_LN];
  362. X
  363. X   struct snmp_session *ss;
  364. X
  365. X   short status;
  366. X
  367. X   char descr[NAME_LN];  /* From meter_info() */
  368. X   unsigned long uptime;
  369. X   unsigned long LastCollectTime;  /* By any collector, not neccessarily us */
  370. X   unsigned char LastCollectPeer[PEER_ADDR_LEN];
  371. X
  372. X   int ruleset, nrules, nactions;
  373. X
  374. X   unsigned long OurLastCollectTime;
  375. X
  376. X   FILE *keys;
  377. X   FILE *flows;
  378. X   FILE *log;
  379. X   };
  380. X
  381. Xstruct meter_status *first_meter;
  382. X
  383. X/* Values for status */
  384. X
  385. X#define    MT_MANAGE    0x0001  /* Manage this meter */
  386. X#define    MT_INFO         0x0002  /* Have basic info */
  387. X#define    MT_UP         0x0004  /* Meter is running */
  388. X#define    MT_REPORTED  0x0008  /* Current status reported */
  389. X
  390. X#ifdef MTR_LIST
  391. X/* #define  CTLFILE  "/usr/local/src/snmp/manager.cfg" */
  392. X#define  CTLFILE  "manager.cfg"
  393. X#endif
  394. X
  395. Xunsigned short getshort(unsigned char *ucp);
  396. Xunsigned long getlong(unsigned char *ucp);
  397. X
  398. Xvoid init_meter();
  399. Xvoid monitor_meter();
  400. Xvoid monitor(struct meter_status *ms);
  401. Xvoid print_meters();
  402. Xvoid meter_print(struct meter_status *ms);
  403. X
  404. Xvoid printaddress(FILE *f,unsigned char *a,unsigned char len);
  405. Xvoid getaddress(unsigned char *a,unsigned char len);
  406. X
  407. Xint scan_rulefile(struct meter_status *ms, int doset, int list);
  408. Xvoid parse_rulefile(struct meter_status *ms, int list);
  409. Xint add_rule(struct meter_status *ms, struct rule_info *ri);
  410. Xint add_action(struct meter_status *ms, struct action_info *ai);
  411. X
  412. Xint same_acct_oid(oid *a, oid *b);
  413. Xint blob_info(struct meter_status *ms, unsigned char *fb, 
  414. X   unsigned long ft, int *fn);
  415. Xint flow_info(struct meter_status *ms, struct flow_info *fi,
  416. X   unsigned long ft, int *fn, int getkey);
  417. X   
  418. Xchar *uptime_string(unsigned long timeticks, char *buf);
  419. X
  420. Xint verbose = 0, testing = 0;
  421. X
  422. Xvoid main(argc,argv)
  423. Xint argc;
  424. Xchar *argv[];
  425. X{
  426. X   struct meter_status *ms;
  427. X   struct snmp_session session, *ssp;
  428. X
  429. X   int arg;
  430. X   char meter[NAME_LN], community[NAME_LN], rfname[NAME_LN],
  431. X      filename[NAME_LN*2];
  432. X   int interval = 0;
  433. X   int syntax = 0;
  434. X
  435. X   meter[0] = community[0] = rfname[0] = NULL;
  436. X
  437. X#ifdef MTR_LIST
  438. X   parse_ctlfile();
  439. X#endif
  440. X
  441. X   init_mib();
  442. X
  443. X   /*  usage: nm meter-name community */
  444. X
  445. X   for (arg = 1; arg < argc; arg++) {
  446. X      if (argv[arg][0] == '-') {
  447. X     switch (argv[arg][1]) {
  448. X     case 'd':
  449. X        snmp_dump_packet++;
  450. X        break;
  451. X     case 'c':
  452. X        if ((interval = atoi(argv[arg]+2)) == 0) interval = 120;
  453. X        break;
  454. X     case 'r':
  455. X        strcpy(rfname, argv[++arg]);
  456. X        break;
  457. X     case 's':
  458. X        syntax++;
  459. X        break;
  460. X     case 't':
  461. X        testing++;
  462. X        break;
  463. X     case 'v':
  464. X        verbose++;
  465. X        break;
  466. X     default:
  467. X        printf("Invalid option: -%c\n", argv[arg][1]);
  468. X        break;
  469. X        }
  470. X     continue;
  471. X     }
  472. X      if (meter[0] == NULL) strcpy(meter,argv[arg]);
  473. X      else if (community[0] == NULL) strcpy(community,argv[arg]);
  474. X      }
  475. X
  476. X   if (meter[0] == NULL) {
  477. X      printf("nm meter-name community\n\n");
  478. X      exit(0);
  479. X      }
  480. X
  481. X   ms = (struct meter_status *)calloc(sizeof(struct meter_status), 1);
  482. X   strcpy(ms->name,meter);
  483. X   strcpy(ms->community,community);
  484. X   if (*rfname) strcpy(ms->rulefile, rfname);
  485. X   else strcpy(ms->rulefile, RULEFILE);
  486. X
  487. X   if (syntax) {  /* For testing rule files */
  488. X      scan_rulefile(ms,0,1);  exit(0);
  489. X      }
  490. X
  491. X   ms->OurLastCollectTime = 2L;
  492. X
  493. X   strcpy(filename,meter);
  494. X   strcat(filename,".log");
  495. X   if ((ms->log = fopen(filename,"wa")) == NULL) {
  496. X      printf("Failed to open %s\n",filename);
  497. X      exit(0);
  498. X      }
  499. X   strcpy(filename,meter);
  500. X   strcat(filename,".keys");
  501. X   if ((ms->keys = fopen(filename,"wa")) == NULL) {
  502. X      printf("Failed to open %s\n",filename);
  503. X      exit(0);
  504. X      }
  505. X   strcpy(filename,meter);
  506. X   strcat(filename,".flows");
  507. X   if ((ms->flows = fopen(filename,"wa")) == NULL) {
  508. X      printf("Failed to open %s\n",filename);
  509. X      exit(0);
  510. X      }
  511. X
  512. X   bzero((char *)&session, sizeof(struct snmp_session));
  513. X   session.peername = ms->name;
  514. X   session.community = ms->community;
  515. X   session.community_len = strlen(ms->community);
  516. X   session.retries = SNMP_DEFAULT_RETRIES;
  517. X   session.timeout = SNMP_DEFAULT_TIMEOUT;
  518. X   session.authenticator = NULL;
  519. X   snmp_synch_setup(&session);
  520. X   ssp = snmp_open(&session);
  521. X   if (ssp == NULL) {
  522. X      printf("Couldn't open snmp to %s\n", session.peername);
  523. X      exit(-1);
  524. X      }
  525. X   ms->ss = ssp;
  526. X
  527. X   ms->status = MT_MANAGE;
  528. X   first_meter = ms;  /* $$$$$$$ */
  529. X
  530. X#ifdef MTR_LIST
  531. X   if (!explicit) add_all_meters();
  532. X#endif
  533. X
  534. X   init_meter();
  535. X
  536. X   if (!interval) {
  537. X      print_meters();
  538. X      exit (0);
  539. X      }
  540. X
  541. X   parse_rulefile(ms,TRUE);  /* Download the rules we want to use */
  542. X
  543. X   for (;;) {
  544. X      sleep(interval);
  545. X
  546. X      monitor_meter();
  547. X      if (verbose) print_meters();
  548. X      }
  549. X   }
  550. X
  551. X#ifdef MTR_LIST
  552. Xvoid parse_ctlfile()
  553. X{
  554. X   struct meter_status *ms, *mp;
  555. X   FILE *fp;
  556. X   char linebuffer[256];
  557. X   char label[128];
  558. X   char community[128];
  559. X   int n;
  560. X
  561. X   if ((fp = fopen(CTLFILE, "r")) == NULL) {
  562. X      perror(CTLFILE);
  563. X      exit(1);
  564. X      }
  565. X
  566. X   while (fgets(linebuffer, sizeof(linebuffer), fp) != NULL) {
  567. X      if (linebuffer[0] < '0' || linebuffer[0] > 'z') continue;
  568. X      n = sscanf(linebuffer, "%s %s", label, community);
  569. X      if (n < 1) continue;
  570. X      ms = (struct meter_status *)calloc(sizeof(struct meter_status), 1);
  571. X      ms->name = savestr(label);
  572. X      ms->community = n > 1 ? savestr(community) : savestr("public");
  573. X      ms->next = NULL;
  574. X
  575. X      if ((mp = first_meter) == NULL) first_meter = ms;
  576. X      else {
  577. X     while (mp->next) mp = mp->next;
  578. X     mp->next = ms;
  579. X     }
  580. X      }
  581. X   }
  582. X
  583. Xvoid add_all_meters()
  584. X{
  585. X   struct meter_status *ms;
  586. X   for (ms = first_meter; ms != NULL; ms = ms->next)
  587. X      ms->status = MT_MANAGE;
  588. X   }
  589. X
  590. Xvoid add_meter(name)
  591. Xchar *name;
  592. X{
  593. X   struct meter_status *ms;
  594. X
  595. X   for (ms = first_meter; ms != NULL; ms = ms->next) {
  596. X      if (strcasecmp(name,ms->name) == 0) break;
  597. X      }
  598. X
  599. X   if (ms == NULL) {
  600. X      struct hostent *hp;
  601. X      u_long addr;
  602. X
  603. X      if ((addr = (u_long)inet_addr(name)) == (u_long)-1) {
  604. X     hp = gethostbyname(name);
  605. X     if (hp != NULL) {
  606. X        for (ms = first_meter; ms != NULL; ms = ms->next) {
  607. X#ifdef h_addr
  608. X           char **ap;
  609. X#endif
  610. X           if (strcasecmp(hp->h_name, ms->name) == 0) break;
  611. X#ifdef h_addr
  612. X           if (hp->h_addr_list == NULL) continue;
  613. X
  614. X           for (ap = hp->h_addr_list; *ap; ap++) {
  615. X          if (addr == *(u_long *)(*ap)) break;
  616. X          }
  617. X           if (*ap) break;
  618. X#else
  619. X           if (addr == *(u_long *)(hp->h_addr)) break;
  620. X#endif
  621. X                    
  622. X           }
  623. X        if (ms == NULL) {
  624. X           printf("No config info for %s\n", name);
  625. X           return;
  626. X           }
  627. X        }
  628. X         else {
  629. X        printf("No config info for %s\n", name);
  630. X        return;
  631. X        }
  632. X     }
  633. X      }
  634. X
  635. X   ms->status = MT_MANAGE;
  636. X   }
  637. X#endif
  638. X
  639. Xvoid init_meter()
  640. X{
  641. X   struct meter_status *ms;
  642. X   int haveone = 0;
  643. X
  644. X   for (ms = first_meter; ms; ms = ms->next) {
  645. X      if (!(ms->status & MT_MANAGE)) continue;
  646. X      haveone++;
  647. X      if (meter_info(ms)) {
  648. X         ms->status |= (MT_UP | MT_INFO);
  649. X         meter_print(ms);
  650. X         }
  651. X      }
  652. X
  653. X   if (!haveone) {
  654. X      printf("No meters to monitor\n");
  655. X      exit(5);
  656. X      }
  657. X   }
  658. X
  659. X
  660. Xvoid monitor_meter()
  661. X{
  662. X   struct meter_status *ms;
  663. X   for (ms = first_meter; ms; ms = ms->next)
  664. X      if (ms->status & MT_MANAGE) monitor(ms);
  665. X   }
  666. X
  667. X/* CAUTION:  Following struct doesn't work because of alignment on 32-bit words
  668. X *
  669. X * struct active_flow_data {  
  670. X *    unsigned short flow_nbr;
  671. X *    unsigned long fwd_bytes, back_bytes;
  672. X *    }; 
  673. X */
  674. X
  675. X#define flow_nbr_x    0
  676. X#define fwd_bytes_x   (flow_nbr_x + sizeof(unsigned short))
  677. X#define back_bytes_x  (fwd_bytes_x + sizeof(unsigned long))
  678. X#define flow_data_sz  (back_bytes_x + sizeof(unsigned long))
  679. X
  680. X#define FLOWBLOBSZ  25
  681. X
  682. Xunsigned short getshort(ucp)
  683. Xunsigned char *ucp;
  684. X{
  685. X   return ucp[0]<<8 | ucp[1];
  686. X   }
  687. X
  688. Xunsigned long getlong(ucp)
  689. Xunsigned char *ucp;
  690. X{
  691. X   return ucp[0]<<24 | ucp[1]<<16 | ucp[2]<<8 | ucp[3];
  692. X   }
  693. X
  694. Xvoid monitor(ms)  /* Called every interval for each meter */
  695. Xstruct meter_status *ms;
  696. X{
  697. X   time_t t;
  698. X   char *ts;
  699. X   unsigned short newflows,activeflows, n;
  700. X   int fn;
  701. X   struct flow_info fi;
  702. X   unsigned char flowblob[FLOWBLOBSZ*flow_data_sz], *afdp;
  703. X   unsigned long fwd_bytes, back_bytes;
  704. X
  705. X   time(&t);  ts = ctime(&t);
  706. X   if (!(ms->status & MT_INFO)) {  /* No info */
  707. X      if (meter_info(ms))  /* Got some */
  708. X     ms->status |= (MT_UP | MT_INFO);
  709. X      return;
  710. X      }
  711. X   if (meter_info(ms) == 0) {  /* Lost contact */
  712. X      if (ms->status & MT_UP) {  /* Was up */
  713. X     fprintf(ms->log,"%19.19s -- %s: No response\n", ts,ms->name);
  714. X     if (verbose) printf("%19.19s -- %s: No response\n", ts,ms->name);
  715. X     }
  716. X      ms->status &= ~MT_UP;  /* Mark as 'down' */
  717. X      return;
  718. X      }
  719. X   if (!(ms->status & MT_UP)) {  /* Have contact now, was down */
  720. X      fprintf(ms->log,"%19.19s -- %s: Regained contact\n", ts,ms->name);
  721. X      if (verbose) printf("%19.19s -- %s: Regained contact\n", ts,ms->name);
  722. X      }
  723. X   ms->status |= MT_UP;
  724. X
  725. X   /* Meter processing .. */
  726. X
  727. X   set_collect_time(ms,1);  /* Tell meter we're starting a collection */
  728. X
  729. X   fprintf(ms->keys, 
  730. X      "## %19.19s %s: New flows from %lu to %lu##\n",
  731. X      ts,ms->name, ms->LastCollectTime,ms->uptime);
  732. X   fn = 1;  newflows = 0;
  733. X   while (flow_info(ms, &fi, ms->OurLastCollectTime,&fn, 1)) {
  734. X      ++newflows;
  735. X      fprintf(ms->keys, "%u %lu %u", fn, fi.FirstTime,fi.PeerAddrType);
  736. X      printaddress(ms->keys, fi.LowPeerAddress,PEER_ADDR_LEN);
  737. X      printaddress(ms->keys, fi.HighPeerAddress,PEER_ADDR_LEN);
  738. X      fprintf(ms->keys,"\n");
  739. X      }
  740. X   fflush(ms->keys);
  741. X
  742. X   fprintf(ms->flows, 
  743. X      "## %19.19s %s: Active flows from %lu to %lu##\n",
  744. X      ts,ms->name, ms->LastCollectTime,ms->uptime);
  745. X   fn = 1;  activeflows = 0;
  746. X   while (blob_info(ms,flowblob, ms->OurLastCollectTime,&fn)) {
  747. X      for (n = 0, afdp = flowblob;  n != FLOWBLOBSZ; 
  748. X            ++n, afdp += flow_data_sz) {
  749. X         fn = ntohs(getshort(afdp + flow_nbr_x));
  750. X         if (fn == 0) break;  /* No more active flows in blob */
  751. X         ++activeflows;
  752. X         fprintf(ms->flows,"%u %lu %lu\n", fn,
  753. X            ntohl(getlong(afdp + fwd_bytes_x)),
  754. X            ntohl(getlong(afdp + back_bytes_x)) );
  755. X         }
  756. X      if (fn == 0) break;  /* Don't bother to look for more */
  757. X      }    
  758. X   fflush(ms->flows);
  759. X
  760. X   ms->OurLastCollectTime = ms->uptime - 1;
  761. X      /* -1 to make sure we don't miss any flows.  We may
  762. X         collect some of them twice, but we don't mind that */
  763. X
  764. X   if (verbose) printf(
  765. X      "%19.19s %s: %d new and %d active flows from %lu to %lu\n",
  766. X      ts,ms->name, newflows,activeflows, ms->LastCollectTime,ms->uptime);
  767. X   fprintf(ms->log, 
  768. X      "## %19.19s %s: %d new and %d active flows from %ld to %ld##\n",
  769. X      ts,ms->name, newflows,activeflows, ms->LastCollectTime,ms->uptime);
  770. X   fflush(ms->log);  
  771. X   }
  772. X
  773. X#define ADD_VAR(v)            snmp_add_null_var(pdu, v, sizeof(v)/sizeof(oid))
  774. X#define ADD_X_VAR(v,n1)       { v[sizeof(v)/sizeof(oid) - 1] = n1; \
  775. X            ADD_VAR(v); }
  776. X#define ADD_X2_VAR(v,n1,n2)   { v[sizeof(v)/sizeof(oid) - 2] = n1; \
  777. X            v[sizeof(v)/sizeof(oid) - 1] = n2; \
  778. X            ADD_VAR(v); }
  779. X
  780. X#define SET_INT(v)            { vars->type = INTEGER; \
  781. X          vars->val.integer = (long *)malloc(vars->val_len = sizeof(long)); \
  782. X        *(vars->val.integer) = (long)v; }
  783. X#define SET_TIMETICKS(v)      { vars->type = TIMETICKS; \
  784. X          vars->val.integer = (long *)malloc(vars->val_len = sizeof(long)); \
  785. X        *(vars->val.integer) = (long)v; }
  786. X#define SET_STRING(v,len)     { vars->type = STRING; \
  787. X        vars->val.string = (u_char *)malloc(RULE_ADDR_LEN) ;\
  788. X        bcopy(v, (char *)vars->val.string, vars->val_len = len); }
  789. X
  790. X#define STRING_VAL(v)         bcopy(vars->val.string, v, vars->val_len)
  791. X#define INT_VAL(v)            v = *(vars->val.integer)
  792. X
  793. Xint set_collect_time(ms,v)  /* Set LastCollectTime for meter - */
  794. Xstruct meter_status *ms;    /*    this tells meter a collection is starting */
  795. Xint v;
  796. X{
  797. X   int i, count, status;
  798. X   struct snmp_pdu *pdu, *response;
  799. X   struct variable_list *vars;
  800. X   pdu = snmp_pdu_create(SET_REQ_MSG);
  801. X   ADD_VAR(o_LastCollectTime);
  802. X   vars = pdu->variables;
  803. X   SET_TIMETICKS(v);
  804. X
  805. X   status = snmp_synch_response(ms->ss, pdu, &response);
  806. X   if (status == STAT_SUCCESS) {
  807. X      if (response->errstat == SNMP_ERR_NOERROR) {
  808. X         printf("Set %d: starting collection\n", ms->ruleset);
  809. X     }
  810. X      else {
  811. X     printf("Error in packet, reason = %s\n",
  812. X        snmp_errstring(response->errstat));
  813. X     if (response->errstat == SNMP_ERR_NOSUCHNAME) {
  814. X        printf("This name does not exist: ");
  815. X        for (count=1, vars = response->variables;
  816. X           vars && count != response->errindex;
  817. X          vars = vars->next_variable, count++) ;
  818. X        if (vars) print_objid(vars->name, vars->name_length);
  819. X        printf("\n");
  820. X        }
  821. X     }
  822. X      }
  823. X   else return 0;
  824. X   snmp_free_pdu(response);
  825. X   return 1;
  826. X   }
  827. X
  828. Xint set_rule_info(ms,setset)  /* 1 to set rule+action set */
  829. Xstruct meter_status *ms;      /* 0 to set rule and actions tables sizes */
  830. Xint setset;
  831. X{
  832. X   int i, count, status;
  833. X   struct snmp_pdu *pdu, *response;
  834. X   struct variable_list *vars;
  835. X   pdu = snmp_pdu_create(SET_REQ_MSG);
  836. X   if (setset) {
  837. X      ADD_VAR(o_CurrentRuleSet);
  838. X         vars = pdu->variables;
  839. X         SET_INT(ms->ruleset);
  840. X      }
  841. X   else {
  842. X      ADD_X_VAR(o_riRuleSize, ms->ruleset);
  843. X         vars = pdu->variables;
  844. X         SET_INT(ms->nrules);
  845. X      ADD_X_VAR(o_riActionSize, ms->ruleset);
  846. X         vars = vars->next_variable;
  847. X         SET_INT(ms->nactions);
  848. X      }
  849. X
  850. X   status = snmp_synch_response(ms->ss, pdu, &response);
  851. X   if (status == STAT_SUCCESS) {
  852. X      if (response->errstat == SNMP_ERR_NOERROR) {
  853. X         if (setset) ("Meter is now using rule+action set %d\n", ms->ruleset);
  854. X         else printf("Set %d: sizes set to %d rules + %d actions\n", 
  855. X            ms->ruleset,ms->nrules,ms->nactions);
  856. X     }
  857. X      else {
  858. X     printf("Error in packet, reason = %s\n",
  859. X        snmp_errstring(response->errstat));
  860. X     if (response->errstat == SNMP_ERR_NOSUCHNAME) {
  861. X        printf("This name does not exist: ");
  862. X        for (count=1, vars = response->variables;
  863. X           vars && count != response->errindex;
  864. X          vars = vars->next_variable, count++) ;
  865. X        if (vars) print_objid(vars->name, vars->name_length);
  866. X        printf("\n");
  867. X        }
  868. X     }
  869. X      }
  870. X   else return 0;
  871. X   snmp_free_pdu(response);
  872. X   return 1;
  873. X   }
  874. X
  875. Xint add_rule(ms,ri)
  876. Xstruct meter_status *ms;
  877. Xstruct rule_info *ri;
  878. X{
  879. X   int i, count, status;
  880. X   struct snmp_pdu *pdu, *response;
  881. X   struct variable_list *vars;
  882. X
  883. X   pdu = snmp_pdu_create(SET_REQ_MSG);
  884. X   ADD_X2_VAR(o_rtSelector, ri->RuleSet,ri->RuleNbr);
  885. X      vars = pdu->variables;
  886. X      SET_INT(ri->RuleSelector);
  887. X   ADD_X2_VAR(o_rtRuleMask, ri->RuleSet,ri->RuleNbr);
  888. X      vars = vars->next_variable;
  889. X      SET_STRING(ri->RuleMask,RULE_ADDR_LEN);
  890. X   ADD_X2_VAR(o_rtMatchedValue, ri->RuleSet,ri->RuleNbr);
  891. X      vars = vars->next_variable;
  892. X      SET_STRING(ri->RuleMatchedValue,RULE_ADDR_LEN);
  893. X   ADD_X2_VAR(o_rtRuleAction, ri->RuleSet,ri->RuleNbr);
  894. X      vars = vars->next_variable;
  895. X      SET_INT(ri->RuleAction);
  896. X   ADD_X2_VAR(o_rtJumpIndex, ri->RuleSet,ri->RuleNbr);
  897. X      vars = vars->next_variable;
  898. X      SET_INT(ri->RuleJumpIndex);
  899. X
  900. X   status = snmp_synch_response(ms->ss, pdu, &response);
  901. X   if (status == STAT_SUCCESS) {
  902. X      if (response->errstat == SNMP_ERR_NOERROR) {
  903. X         printf("Rule %d added to table %d\n", ri->RuleNbr,ri->RuleSet);
  904. X     }
  905. X      else {
  906. X     printf("Error in packet, reason = %s\n",
  907. X        snmp_errstring(response->errstat));
  908. X     if (response->errstat == SNMP_ERR_NOSUCHNAME) {
  909. X        printf("This name does not exist: ");
  910. X        for (count=1, vars = response->variables;
  911. X           vars && count != response->errindex;
  912. X          vars = vars->next_variable, count++) ;
  913. X        if (vars) print_objid(vars->name, vars->name_length);
  914. X        printf("\n");
  915. X        }
  916. X     }
  917. X      }
  918. X   else return 0;
  919. X   snmp_free_pdu(response);
  920. X   return 1;
  921. X   }
  922. X
  923. Xint add_action(ms,ai)
  924. Xstruct meter_status *ms;
  925. Xstruct action_info *ai;
  926. X{
  927. X   int i, count, status;
  928. X   struct snmp_pdu *pdu, *response;
  929. X   struct variable_list *vars;
  930. X
  931. X   pdu = snmp_pdu_create(SET_REQ_MSG);
  932. X   ADD_X2_VAR(o_atLowPeerType, ai->ActionSet,ai->ActionNbr);
  933. X      vars = pdu->variables;
  934. X      SET_INT(ai->PeerAddrType);
  935. X   ADD_X2_VAR(o_atLowPeerAddress, ai->ActionSet,ai->ActionNbr);
  936. X      vars = vars->next_variable;
  937. X      SET_STRING(ai->LowPeerAddress,PEER_ADDR_LEN);
  938. X   ADD_X2_VAR(o_atLowPeerMask, ai->ActionSet,ai->ActionNbr);
  939. X      vars = vars->next_variable;
  940. X      SET_STRING(ai->LowPeerMask,PEER_ADDR_LEN);
  941. X   ADD_X2_VAR(o_atHighPeerAddress, ai->ActionSet,ai->ActionNbr);
  942. X      vars = vars->next_variable;
  943. X      SET_STRING(ai->HighPeerAddress,PEER_ADDR_LEN);
  944. X   ADD_X2_VAR(o_atHighPeerMask, ai->ActionSet,ai->ActionNbr);
  945. X      vars = vars->next_variable;
  946. X      SET_STRING(ai->HighPeerMask,PEER_ADDR_LEN);
  947. X
  948. X   status = snmp_synch_response(ms->ss, pdu, &response);
  949. X   if (status == STAT_SUCCESS) {
  950. X      if (response->errstat == SNMP_ERR_NOERROR) {
  951. X         printf("Action %d added to table %d\n", ai->ActionNbr,ai->ActionSet);
  952. X     }
  953. X      else {
  954. X     printf("Error in packet, reason = %s\n",
  955. X        snmp_errstring(response->errstat));
  956. X     if (response->errstat == SNMP_ERR_NOSUCHNAME) {
  957. X        printf("This name does not exist: ");
  958. X        for (count=1, vars = response->variables;
  959. X           vars && count != response->errindex;
  960. X          vars = vars->next_variable, count++) ;
  961. X        if (vars) print_objid(vars->name, vars->name_length);
  962. X        printf("\n");
  963. X        }
  964. X     }
  965. X      }
  966. X   else return 0;
  967. X   snmp_free_pdu(response);
  968. X   return 1;
  969. X   }
  970. X
  971. Xint same_acct_oid(oid *a, oid *b)  
  972. X   /* Compare oids for equality within internet-accounting MIB */
  973. X{
  974. X   int j;
  975. X   for (j = 6; j != 10; ++j) {
  976. X      if (a[j] != b[j]) return 0;
  977. X      }
  978. X   return 1;
  979. X   }
  980. X
  981. Xint blob_info(struct meter_status *ms, unsigned char *fb,
  982. X   unsigned long ft, int *fn)
  983. X{
  984. X   int i, count, status;
  985. X   struct snmp_pdu *pdu, *response;
  986. X   struct variable_list *vars;
  987. X
  988. X   if (testing) printf("blob_info(ms,fb,ft=%lu,fn=%d)\n",ft,*fn);
  989. X   pdu = snmp_pdu_create(GETNEXT_REQ_MSG);
  990. X   ADD_X2_VAR(o_ftActiveFlowBlob,ft,*fn)
  991. X   status = snmp_synch_response(ms->ss, pdu, &response);
  992. X   if (status == STAT_SUCCESS) {
  993. X      if (response->errstat == SNMP_ERR_NOERROR) {
  994. X     vars = response->variables;
  995. X         if (!same_acct_oid(vars->name,o_ftActiveFlowBlob)) 
  996. X            return 0;  /* No more flows with last-active time > ft */
  997. X     STRING_VAL(fb);
  998. X     }
  999. X      else if (response->errstat == SNMP_ERR_NOSUCHNAME) return 0;
  1000. X      else {
  1001. X     printf("Error in packet, reason = %s\n",
  1002. X        snmp_errstring(response->errstat));
  1003. X     printf("This name does not exist: ");
  1004. X     for (count=1, vars = response->variables;
  1005. X        vars && count != response->errindex;
  1006. X     vars = vars->next_variable, count++) ;
  1007. X     if (vars) print_objid(vars->name, vars->name_length);
  1008. X     printf("\n");
  1009. X     }
  1010. X      }
  1011. X   else return 0;
  1012. X   snmp_free_pdu(response);
  1013. X   return 1;
  1014. X   }
  1015. X
  1016. Xint flow_info(struct meter_status *ms, struct flow_info *fi,
  1017. X   unsigned long ft, int *fn, int getkey)
  1018. X  /* getkey = 1 to get keys created after ft, 
  1019. X              0 to get flows active after ft */
  1020. X{
  1021. X   int j, count, status;
  1022. X   struct snmp_pdu *pdu, *response;
  1023. X   struct variable_list *vars;
  1024. X
  1025. X   if (testing) printf("flow_info(ms,fi,ft=%lu,fn=%d,getkey=%d)\n",
  1026. X      ft,*fn,getkey);
  1027. X
  1028. X   pdu = snmp_pdu_create(GETNEXT_REQ_MSG);
  1029. X   if (getkey) ADD_X2_VAR(o_ftCreateIndex,ft,*fn)
  1030. X   else ADD_X2_VAR(o_ftActiveIndex,ft,*fn)
  1031. X   status = snmp_synch_response(ms->ss, pdu, &response);
  1032. X   if (status == STAT_SUCCESS) {
  1033. X      if (response->errstat == SNMP_ERR_NOERROR) {
  1034. X     vars = response->variables;
  1035. X         if (getkey) {
  1036. X            if (!same_acct_oid(vars->name,o_ftCreateIndex)) 
  1037. X               return 0;  /* No more flows with create time > ft */
  1038. X            }
  1039. X         else {
  1040. X            if (!same_acct_oid(vars->name,o_ftActiveIndex)) 
  1041. X               return 0;  /* No more flows with last-active time > ft */
  1042. X        }
  1043. X     INT_VAL(*fn);  /* Index of next flow created or active after ft */
  1044. X     }
  1045. X      else if (response->errstat == SNMP_ERR_NOSUCHNAME) return 0;
  1046. X      else {
  1047. X     printf("Error in packet, reason = %s\n",
  1048. X        snmp_errstring(response->errstat));
  1049. X     printf("This name does not exist: ");
  1050. X     for (count=1, vars = response->variables;
  1051. X        vars && count != response->errindex;
  1052. X     vars = vars->next_variable, count++) ;
  1053. X     if (vars) print_objid(vars->name, vars->name_length);
  1054. X      printf("\n");
  1055. X     }
  1056. X      }
  1057. X   else return 0;
  1058. X   snmp_free_pdu(response);
  1059. X
  1060. X   pdu = snmp_pdu_create(GET_REQ_MSG);
  1061. X   if (getkey) {
  1062. X      ADD_X_VAR(o_ftLowPeerType,*fn);
  1063. X      ADD_X_VAR(o_ftLowPeerAddress,*fn);
  1064. X      ADD_X_VAR(o_ftHighPeerAddress,*fn);
  1065. X      ADD_X_VAR(o_ftFirstTime,*fn);
  1066. X      }
  1067. X   else {
  1068. X      ADD_X_VAR(o_ftUpOctets,*fn);
  1069. X      ADD_X_VAR(o_ftDownOctets,*fn);
  1070. X      ADD_X_VAR(o_ftLastTime,*fn);
  1071. X      }
  1072. X   status = snmp_synch_response(ms->ss, pdu, &response);
  1073. X   if (status == STAT_SUCCESS) {
  1074. X      if (response->errstat == SNMP_ERR_NOERROR) {
  1075. X     vars = response->variables;
  1076. X     if (getkey) {
  1077. X        INT_VAL(fi->PeerAddrType);
  1078. X        vars = vars->next_variable;
  1079. X        STRING_VAL(fi->LowPeerAddress);
  1080. X        vars = vars->next_variable;
  1081. X        STRING_VAL(fi->HighPeerAddress);
  1082. X        vars = vars->next_variable;
  1083. X        INT_VAL(fi->FirstTime);
  1084. X        vars = vars->next_variable;
  1085. X        }
  1086. X     else {
  1087. X        INT_VAL(fi->FwdBytes);
  1088. X        vars = vars->next_variable;
  1089. X        INT_VAL(fi->BackBytes);
  1090. X        vars = vars->next_variable;
  1091. X        INT_VAL(fi->LastTime);
  1092. X        }
  1093. X     }
  1094. X      else {
  1095. X     printf("Error in packet, reason = %s\n",
  1096. X        snmp_errstring(response->errstat));
  1097. X     if (response->errstat == SNMP_ERR_NOSUCHNAME) {
  1098. X        printf("This name does not exist: ");
  1099. X        for (count=1, vars = response->variables;
  1100. X           vars && count != response->errindex;
  1101. X          vars = vars->next_variable, count++) ;
  1102. X        if (vars) print_objid(vars->name, vars->name_length);
  1103. X        printf("\n");
  1104. X        }
  1105. X     }
  1106. X      }
  1107. X   else return 0;
  1108. X   snmp_free_pdu(response);
  1109. X   return 1;
  1110. X   }
  1111. X
  1112. Xint meter_info(ms)
  1113. Xstruct meter_status *ms;
  1114. X{
  1115. X   int i, count, status;
  1116. X   struct snmp_pdu *pdu, *response;
  1117. X   struct variable_list *vars;
  1118. X
  1119. X   if (testing) printf("meter_info(ms)\n");
  1120. X   pdu = snmp_pdu_create(GET_REQ_MSG);
  1121. X   ADD_VAR(o_sysDescr);
  1122. X   ADD_VAR(o_sysUpTime);
  1123. X   ADD_VAR(o_LastCollectTime);
  1124. X   status = snmp_synch_response(ms->ss, pdu, &response);
  1125. X   if (status == STAT_SUCCESS) {
  1126. X      if (response->errstat == SNMP_ERR_NOERROR) {
  1127. X     vars = response->variables;
  1128. X     STRING_VAL(ms->descr);
  1129. X         vars = vars->next_variable;
  1130. X     INT_VAL(ms->uptime);
  1131. X         vars = vars->next_variable;
  1132. X     INT_VAL(ms->LastCollectTime);
  1133. X     }
  1134. X      else {
  1135. X     printf("Error in packet, reason = %s\n",
  1136. X        snmp_errstring(response->errstat));
  1137. X     if (response->errstat == SNMP_ERR_NOSUCHNAME) {
  1138. X        printf("This name does not exist: ");
  1139. X        for (count=1, vars = response->variables;
  1140. X           vars && count != response->errindex;
  1141. X          vars = vars->next_variable, count++) ;
  1142. X        if (vars) print_objid(vars->name, vars->name_length);
  1143. X        printf("\n");
  1144. X        }
  1145. X     }
  1146. X      }
  1147. X   else return 0;
  1148. X   snmp_free_pdu(response);
  1149. X   return 1;
  1150. X   }
  1151. X
  1152. Xvoid print_meters()
  1153. X{
  1154. X   struct meter_status *ms;
  1155. X   for (ms = first_meter; ms; ms = ms->next)
  1156. X      if (ms->status & MT_MANAGE) meter_print(ms);
  1157. X   }
  1158. X
  1159. Xvoid meter_print(ms)
  1160. Xstruct meter_status *ms;
  1161. X{
  1162. X   struct timeval tv;
  1163. X   char buf[32];
  1164. X   time_t t;   char tsbuf[32];
  1165. X
  1166. X   time(&t);  strcpy(tsbuf,ctime(&t));
  1167. X
  1168. X   gettimeofday(&tv, (struct timezone *)0);
  1169. X   tv.tv_sec -= ms->uptime / 100;
  1170. X   if ((ms->uptime % 100)*10000 > tv.tv_usec) {
  1171. X      tv.tv_sec--;
  1172. X      tv.tv_usec += 1000000;
  1173. X      }
  1174. X   tv.tv_usec -= (ms->uptime % 100)*10000;
  1175. X
  1176. X   fprintf(ms->log,
  1177. X      "%19.19s -- %s: %s\n\tUp %s (since %.24s)\n",
  1178. X     tsbuf,ms->name, ms->descr, uptime_string(ms->uptime, buf),
  1179. X     ctime(&tv.tv_sec));
  1180. X   if (verbose) printf(
  1181. X      "%19.19s -- %s: %s\n\tUp %s (since %.24s)\n",
  1182. X     tsbuf,ms->name, ms->descr, uptime_string(ms->uptime, buf),
  1183. X     ctime(&tv.tv_sec));
  1184. X   }
  1185. X
  1186. X
  1187. Xchar *uptime_string(timeticks, buf)
  1188. Xunsigned long timeticks;
  1189. Xchar *buf;
  1190. X{
  1191. X   int    seconds, minutes, hours, days;
  1192. X
  1193. X   timeticks /= 100;
  1194. X   days = timeticks / (60 * 60 * 24);
  1195. X   timeticks %= (60 * 60 * 24);
  1196. X
  1197. X   hours = timeticks / (60 * 60);
  1198. X   timeticks %= (60 * 60);
  1199. X
  1200. X   minutes = timeticks / 60;
  1201. X   seconds = timeticks % 60;
  1202. X
  1203. X   if (days == 0){
  1204. X      sprintf(buf, "%d:%02d:%02d", hours, minutes, seconds);
  1205. X      }
  1206. X   else if (days == 1) {
  1207. X      sprintf(buf, "%d day, %d:%02d:%02d",
  1208. X     days, hours, minutes, seconds);
  1209. X      }
  1210. X   else {
  1211. X      sprintf(buf, "%d days, %d:%02d:%02d",
  1212. X     days, hours, minutes, seconds);
  1213. X      }
  1214. X   return buf;
  1215. X   }
  1216. X
  1217. Xvoid printaddress(f,a,len)
  1218. XFILE *f;
  1219. Xunsigned char *a, len;
  1220. X{
  1221. X   int j;
  1222. X   fprintf(f," %u", a[0]);
  1223. X   for (j = 1; j != len; ++j) fprintf(f,".%u", a[j]);
  1224. X   }
  1225. X
  1226. X
  1227. XFILE *rfp;  /* For rules file */
  1228. Xchar inbuf[256], *ibp;
  1229. Xint lic, ic,  /* Last input char, current input char */
  1230. X   iblisted, rule_line, rferrors;
  1231. X
  1232. Xint nextchar()
  1233. X{
  1234. X   lic = ic;
  1235. X   for (;;) {
  1236. X      if (lic == '\n') {
  1237. X     if (fgets(inbuf, sizeof(inbuf), rfp) == NULL) return ic = EOF;
  1238. X     iblisted = 0;  ++rule_line;
  1239. X     ibp = inbuf;
  1240. X     }
  1241. X      ic = *ibp++;
  1242. X      if (ic == '#') lic = '\n';  /* Ignore comments */
  1243. X      else return ic;
  1244. X      }
  1245. X   }
  1246. X
  1247. Xint wordis(p,w)
  1248. Xchar *p, *w;
  1249. X{
  1250. X   return strncmp(p,w,strlen(w)) == 0;
  1251. X   }
  1252. X
  1253. Xint getword()
  1254. X{
  1255. X   char wbuf[30], *wp = wbuf;
  1256. X   for (;;) {
  1257. X      *wp++ = tolower(ic);
  1258. X      nextchar(rfp);
  1259. X      if (ic == EOF) return EOF;
  1260. X      if (!isalpha(ic)) break;
  1261. X      }
  1262. X
  1263. X   if (wordis(wbuf,"null")) return RS_NULL;
  1264. X   if (wordis(wbuf,"lowpeertype")) return RS_LOWPEERTYPE;
  1265. X   if (wordis(wbuf,"lowpeeraddress")) return RS_LOWPEERADDR;
  1266. X   if (wordis(wbuf,"highpeeraddress")) return RS_HIPEERADDR;
  1267. X
  1268. X   if (wordis(wbuf,"ip")) return AT_IP;
  1269. X   if (wordis(wbuf,"novell")) return AT_NOVELL;
  1270. X   if (wordis(wbuf,"decnet")) return AT_DECNET;
  1271. X   if (wordis(wbuf,"ethertalk")) return AT_ETHERTALK;
  1272. X
  1273. X   if (wordis(wbuf,"count")) return RA_COUNT;
  1274. X   if (wordis(wbuf,"tally")) return RA_TALLY;
  1275. X   if (wordis(wbuf,"aggregate")) return RA_AGGREGATE;
  1276. X   if (wordis(wbuf,"succeed")) return RA_SUCCEED;
  1277. X   if (wordis(wbuf,"fail")) return RA_FAIL;
  1278. X   if (wordis(wbuf,"pushto")) return RA_PUSHTO;
  1279. X   if (wordis(wbuf,"popto")) return RA_POPTO;
  1280. X   if (wordis(wbuf,"goto")) return RA_GOTO;
  1281. X
  1282. X   if (wordis(wbuf,"set")) return RF_SET;
  1283. X   if (wordis(wbuf,"rules")) return RF_RULES;
  1284. X   if (wordis(wbuf,"actions")) return RF_ACTIONS;
  1285. X
  1286. X   if (!iblisted) {
  1287. X      printf("RULEFILE line %d: %s\n", rule_line,inbuf);
  1288. X      iblisted = 1;
  1289. X      }
  1290. X   printf("Unknown word %s !!!\n", wbuf);
  1291. X   ++rferrors;
  1292. X   return 0;
  1293. X   }
  1294. X
  1295. Xint getnbr()
  1296. X{
  1297. X   int v = 0;
  1298. X   for (;;) {
  1299. X      if (ic == EOF) return EOF;
  1300. X      if (isdigit(ic)) break;
  1301. X      else if (isalpha(ic)) return getword();
  1302. X      else nextchar(rfp);
  1303. X      }
  1304. X   for (;;) {
  1305. X      v = v*10 + ic-'0';
  1306. X      if (nextchar(ic) == EOF) return EOF;
  1307. X      if (!isdigit(ic)) break;
  1308. X      }
  1309. X   if (v > 255) {
  1310. X      if (!iblisted) {
  1311. X     printf("RULEFILE line %d: %s\n", rule_line,inbuf);
  1312. X     iblisted = 1;
  1313. X     }
  1314. X      printf("Number > 255 !!!\n");
  1315. X      ++rferrors;
  1316. X      }
  1317. X   return v;
  1318. X   }
  1319. X
  1320. Xvoid getaddress(a,len)
  1321. Xunsigned char *a, len;
  1322. X{
  1323. X   int j;
  1324. X   for (j = 0; j != len; ++j) {
  1325. X      a[j] = getnbr();
  1326. X      if (ic != '.') {  /* End of address; pad with zeroes */
  1327. X         for (++j; j != len; ++j) a[j] = 0;
  1328. X         return;
  1329. X         }
  1330. X      }
  1331. X   }
  1332. X
  1333. Xint scan_rulefile(ms,doset,list)
  1334. Xstruct meter_status *ms;
  1335. Xint doset,list;
  1336. X{
  1337. X   struct rule_info ri;
  1338. X   struct action_info ai;
  1339. X   int rule_set, nrules, nactions, n, kind;
  1340. X
  1341. X   if ((rfp = fopen(ms->rulefile, "r")) == NULL) {
  1342. X      perror(ms->rulefile);
  1343. X      printf("   -> Using meter's default rules <-\n\n");
  1344. X      return 0;  /* Fail */
  1345. X      }
  1346. X
  1347. X   rferrors = 0;
  1348. X   ic = '\n';  rule_set = 2;  /* Default rule+action set */
  1349. X   nrules = nactions = 0;  kind = RF_RULES;
  1350. X   for (;;) {
  1351. X      do {  /* First char of a line */
  1352. X     nextchar(rfp);
  1353. X     if (ic == EOF) break;
  1354. X     } while (lic != '\n');
  1355. X      if (ic == EOF) break;
  1356. X      n = getnbr();  /* What kind of line is it? */
  1357. X      if (n == RF_SET) {
  1358. X         ri.RuleSet = ai.ActionSet = rule_set = getnbr();
  1359. X         kind = RF_RULES;  
  1360. X         continue;
  1361. X         }
  1362. X      else if (n == RF_RULES) {
  1363. X         kind = RF_RULES;  continue;
  1364. X         }
  1365. X      if (n == RF_ACTIONS) {
  1366. X         kind = RF_ACTIONS;   continue;
  1367. X         }
  1368. X
  1369. X      if (kind == RF_RULES) {
  1370. X         ri.RuleSelector = n;
  1371. X         getaddress(ri.RuleMask,RULE_ADDR_LEN);
  1372. X         if (ic == EOF) break;
  1373. X         getaddress(ri.RuleMatchedValue,RULE_ADDR_LEN);
  1374. X         if (ic == EOF) break;
  1375. X         ri.RuleAction = getnbr();
  1376. X         if (ic == EOF) break;
  1377. X         ri.RuleJumpIndex = getnbr();
  1378. X         if (ic == EOF) break;
  1379. X         ri.RuleNbr = ++nrules;
  1380. X         if (list) {
  1381. X        printf("Rule %d,%d:  %d  ", rule_set,nrules,ri.RuleSelector);
  1382. X        printaddress(stdout, ri.RuleMask, RULE_ADDR_LEN);
  1383. X        printaddress(stdout, ri.RuleMatchedValue,RULE_ADDR_LEN);
  1384. X        printf(" %d %d\n", ri.RuleAction,ri.RuleJumpIndex);
  1385. X        }
  1386. X         if (doset) add_rule(ms,&ri);  /* Add rule to meter's rule table */
  1387. X     }
  1388. X
  1389. X      if (kind == RF_ACTIONS) {
  1390. X         ai.PeerAddrType = n;
  1391. X         if (ic == EOF) break;
  1392. X         getaddress(ai.LowPeerAddress,PEER_ADDR_LEN);
  1393. X         if (ic == EOF) break;
  1394. X         getaddress(ai.LowPeerMask,PEER_ADDR_LEN);
  1395. X         if (ic == EOF) break;
  1396. X         getaddress(ai.HighPeerAddress,PEER_ADDR_LEN);
  1397. X         if (ic == EOF) break;
  1398. X         getaddress(ai.HighPeerMask,PEER_ADDR_LEN);
  1399. X         if (ic == EOF) break;
  1400. X         ai.ActionNbr = ++nactions;
  1401. X         if (list) {
  1402. X        printf("Action %d,%d:  %d  ", rule_set,nactions,ai.PeerAddrType);
  1403. X        printaddress(stdout, ai.LowPeerAddress,PEER_ADDR_LEN);
  1404. X        printaddress(stdout, ai.LowPeerMask,PEER_ADDR_LEN);
  1405. X            printf("  ");
  1406. X        printaddress(stdout, ai.HighPeerAddress,PEER_ADDR_LEN);
  1407. X        printaddress(stdout, ai.HighPeerMask,PEER_ADDR_LEN);
  1408. X        printf("\n");
  1409. X        }
  1410. X      if (doset) add_action(ms,&ai);  /* Add rule to meter's action table */
  1411. X     }
  1412. X     }
  1413. X
  1414. X   fclose(rfp);
  1415. X   if (rferrors == 0) {
  1416. X      ms->ruleset = rule_set;  ms->nrules = nrules;  ms->nactions = nactions;
  1417. X      return 1;  /* Succeed */
  1418. X      }
  1419. X   return 0;  /* Fail */
  1420. X   }
  1421. X
  1422. Xvoid parse_rulefile(ms,list)
  1423. Xstruct meter_status *ms;
  1424. Xint list;
  1425. X{
  1426. X   if (scan_rulefile(ms,0,list)) {  /* Rulefile is OK */
  1427. X      if (set_rule_info(ms,0)) {  /* Set rule+action table sizes */
  1428. X         scan_rulefile(ms,1,0);  /* Download the rules and actions */
  1429. X         set_rule_info(ms,1);  /* Tell meter to start using new rules */
  1430. X         }
  1431. X      }
  1432. X   }
  1433. END_OF_FILE
  1434.   if test 43638 -ne `wc -c <'netramet/src/manager/nm.jul.c'`; then
  1435.     echo shar: \"'netramet/src/manager/nm.jul.c'\" unpacked with wrong size!
  1436.   fi
  1437.   # end of 'netramet/src/manager/nm.jul.c'
  1438. fi
  1439. if test -f 'netramet/src/manager/nmc.c' -a "${1}" != "-c" ; then 
  1440.   echo shar: Will not clobber existing file \"'netramet/src/manager/nmc.c'\"
  1441. else
  1442.   echo shar: Extracting \"'netramet/src/manager/nmc.c'\" \(17129 characters\)
  1443.   sed "s/^X//" >'netramet/src/manager/nmc.c' <<'END_OF_FILE'
  1444. X/* 1430, Wed 13 Oct 93
  1445. X
  1446. X   NMC.C:  First attempt at a manager for the AU Accounting Meter
  1447. X
  1448. X   Copyright (C) 1992,1993 by Nevil Brownlee,
  1449. X   Computer Centre,  University of Auckland */
  1450. X
  1451. X#include <sys/param.h>
  1452. X#include <sys/types.h>
  1453. X#include <netinet/in.h>
  1454. X#include <netdb.h>
  1455. X
  1456. X#include <stdio.h>
  1457. X#include <ctype.h>
  1458. X#include <sys/time.h>
  1459. X#include <errno.h>
  1460. X
  1461. X#include <string.h>
  1462. X#include <malloc.h>
  1463. X
  1464. X#include "ausnmp.h"
  1465. X
  1466. X#include "snmp.h"
  1467. X#include "snmpimpl.h"
  1468. X#include "asn1.h"
  1469. X#include "snmpclnt.h"
  1470. X#include "snmpapi.h"
  1471. X#include "mib.h"
  1472. X
  1473. X#define EXTERN
  1474. X#include "nmc.h"
  1475. X
  1476. Xint create_meter(struct meter_status *ms)
  1477. X{
  1478. X   char filename[NAME_LN*2];
  1479. X   time_t t;  char *ts;
  1480. X   unsigned char a,b, n;
  1481. X
  1482. X   if (ms->name[0] == NULL || ms->community == 0) {
  1483. X      printf("Meter name or community not specified !!!\n");
  1484. X      return 0;
  1485. X      }
  1486. X
  1487. X   if (!start_snmp_session(ms)) return 0;
  1488. X
  1489. X   ms->status = MT_MANAGE;
  1490. X   if (meter_info(ms)) {
  1491. X      ms->status |= (MT_UP | MT_INFO);
  1492. X      meter_print(stdout,ms);
  1493. X      meter_print(log,ms);
  1494. X      fflush(log);
  1495. X      }
  1496. X   else {
  1497. X      printf("Couldn't get meter info from %s\n",ms->name);
  1498. X      fprintf(log,"Couldn't get meter info from %s\n",ms->name);
  1499. X      fflush(log);
  1500. X      return 0;
  1501. X      }
  1502. X
  1503. X   set_meter_params(ms);
  1504. X
  1505. X   if (ms->rulefile[0] == NULL)  /* No rule file specified */
  1506. X      ms->ruleset = ms->CurrentRuleSet;
  1507. X   else {  /* Download the rules we want to use */
  1508. X      parse_rulefile(ms,listrules);
  1509. X      if (rferrors != 0) return 0;
  1510. X      }
  1511. X   ++nmeters;
  1512. X
  1513. X   ms->OurLastCollectTime = 1L;
  1514. X   ms->snmp_delay = 90;  /* Wait 90 ms after an snmp request */
  1515. X
  1516. X   sprintf(filename, "%s.flows", ms->name);  /* Open flows file */
  1517. X   ms->flows = wfopen(filename);
  1518. X
  1519. X   time(&t);  ts = fmt_time(&t);
  1520. X   fprintf(ms->flows, 
  1521. X      "##NeTraMet v2.2:  -c%d -r %s %s  %u flows  starting at %s\n",
  1522. X      interval,ms->rulefile,ms->name, ms->MaxFlows, ts);
  1523. X   fprintf(ms->flows, "#Format: ");
  1524. X   if ((n = ms->format[a = 0]) != NULL) for (;;) {
  1525. X      for (b = 1; attribs[b].index != n; ++b) ;
  1526. X      fprintf(ms->flows,attribs[b].name);
  1527. X      if ((n = ms->format[a+1]) == NULL) break;
  1528. X      fprintf(ms->flows,ms->separator[a++]);
  1529. X      }
  1530. X   fprintf(ms->flows,"\n");
  1531. X   fflush(ms->flows);
  1532. X   }
  1533. X
  1534. Xchar cfname[NAME_LN], rfname[NAME_LN],
  1535. X   meter[NAME_LN], community[NAME_LN];
  1536. X
  1537. Xvoid main(argc,argv)
  1538. Xint argc;
  1539. Xchar *argv[];
  1540. X{
  1541. X   int syntax;
  1542. X   char *ap, arg[NAME_LN];
  1543. X   int a;
  1544. X   time_t t1,t2;  int busy_seconds;
  1545. X   struct meter_status *ms, *nms;
  1546. X
  1547. X   if (argc < 2) {
  1548. X      printf("nm [options] meter-name community\n\n");
  1549. X      exit(0);
  1550. X      }
  1551. X
  1552. X   syntax = verbose = testing = listrules = 0;
  1553. X   interval = 120;  /* Default 2 minutes */
  1554. X   strcpy(cfname, CFGFILE);
  1555. X   rfname[0] = meter[0] = community[0] = NULL;
  1556. X
  1557. X   for (a = 1; a < argc; ++a) {
  1558. X      if (argv[a][0] == '-') {
  1559. X     switch (argv[a][1]) {
  1560. X     case 'd':
  1561. X        snmp_dump_packet++;
  1562. X        break;
  1563. X     case 'c':
  1564. X            ap = argv[a]+2;
  1565. X            if (*ap == NULL) ap = argv[++a];
  1566. X        interval = atoi(ap);
  1567. X        break;
  1568. X     case 'l':
  1569. X        listrules++;
  1570. X        break;
  1571. X     case 'r':
  1572. X        strcpy(rfname, argv[++a]);  /* Rule file name */
  1573. X        break;
  1574. X     case 'f':
  1575. X        strcpy(cfname, argv[++a]);  /* Config file name */
  1576. X        break;
  1577. X     case 's':
  1578. X        syntax++;
  1579. X        break;
  1580. X     case 't':
  1581. X        testing++;
  1582. X        break;
  1583. X     case 'v':
  1584. X        verbose++;
  1585. X        break;
  1586. X     default:
  1587. X        printf("Invalid option: -%c\n", argv[a][1]);
  1588. X        break;
  1589. X        }
  1590. X     continue;
  1591. X     }
  1592. X      if (meter[0] == NULL) strcpy(meter,argv[a]);
  1593. X      else if (community[0] == NULL) strcpy(community,argv[a]);
  1594. X      }
  1595. X
  1596. X   if (syntax) {  /* Test a rule file */
  1597. X      ms = (struct meter_status *)calloc(sizeof(struct meter_status), 1);
  1598. X      strcpy(ms->rulefile,rfname);
  1599. X      scan_rulefile(ms,0,1);
  1600. X      printf("\n%d errors in rule file %s\n\n", rferrors,rfname);
  1601. X      exit(0);
  1602. X      }
  1603. X
  1604. X   init_mib();  /* Initialise SNMP handler */
  1605. X
  1606. X   log = wfopen(LOGFILE);
  1607. X   time(&t1);
  1608. X   if (!parse_open(cfname)) {  /* No config file */
  1609. X      first_meter = (struct meter_status *)calloc
  1610. X         (sizeof(struct meter_status), 1);
  1611. X      strcpy(first_meter->rulefile,rfname);
  1612. X      strcpy(first_meter->name,meter);
  1613. X      strcpy((char *)first_meter->community,community);
  1614. X      }
  1615. X   else for (first_meter = NULL; ; ) {  /* Parse config file */
  1616. X      ms = (struct meter_status *)calloc(sizeof(struct meter_status), 1);
  1617. X      strcpy(ms->rulefile,rfname);
  1618. X      do {  /* Start with first char of a line */
  1619. X     nextchar();
  1620. X     if (ic == EOF) break;
  1621. X     } while (lic != '\n');
  1622. X      if (ic == EOF) break;
  1623. X      getarg(arg);
  1624. X      for ( ; arg[0] == '-'; ) {
  1625. X         ap = &arg[2];
  1626. X         switch (arg[1]) {
  1627. X         case 'g':
  1628. X            if (*ap == NULL) getarg(ap = arg);
  1629. X        ms->GCIntervalReqd = atoi(ap);
  1630. X            break;
  1631. X         case 'h':
  1632. X            if (*ap == NULL) getarg(ap = arg);
  1633. X        ms->HighWaterMark = atoi(ap);
  1634. X            break;
  1635. X         case 'i':
  1636. X            if (*ap == NULL) getarg(ap = arg);
  1637. X        ms->InactivityTime = atoi(ap);
  1638. X            break;
  1639. X         case 'r':
  1640. X            getarg(ms->rulefile);
  1641. X            break;
  1642. X            }
  1643. X         getarg(arg);
  1644. X         }
  1645. X      strcpy(ms->name,arg);
  1646. X      getarg((char *)ms->community);
  1647. X      if (first_meter == NULL) first_meter = ms;
  1648. X      else for (nms = first_meter; ; nms = nms->next) {
  1649. X         if (nms->next == NULL) {
  1650. X            nms->next = ms;  break;
  1651. X            }
  1652. X         }
  1653. X      }
  1654. X
  1655. X   for (nmeters = 0, ms = first_meter; ms; ms = ms->next)
  1656. X      create_meter(ms);
  1657. X
  1658. X   if (nmeters == 0) {
  1659. X      printf("No meters to monitor !!!\n");
  1660. X      exit(0);
  1661. X      }
  1662. X
  1663. X   for (;;) {
  1664. X      for (ms = first_meter; ms; ms = ms->next)
  1665. X         if (ms->status & MT_MANAGE) monitor(ms);
  1666. X
  1667. X      if (verbose) {
  1668. X         for (ms = first_meter; ms; ms = ms->next)
  1669. X            if (ms->status & MT_MANAGE) meter_print(stdout,ms);
  1670. X         }
  1671. X
  1672. X      if (interval == 0) exit();
  1673. X      time(&t2);  busy_seconds = t2-t1;
  1674. X      if (busy_seconds < interval) sleep(interval-busy_seconds);
  1675. X      time(&t1);
  1676. X      }
  1677. X   }
  1678. X
  1679. X
  1680. Xvoid write_attrib(FILE *f, struct flow_info *fp, unsigned char col)
  1681. X{
  1682. X   switch(col) {
  1683. X   case FTFLOWINDEX:  /* Used to synchronise column blobs */
  1684. X      fprintf(f,"%u",fp->FlowIndex);
  1685. X      break;
  1686. X   case FTFLOWSTATUS:
  1687. X      fprintf(f,"%u",fp->FlowStatus);
  1688. X      break;
  1689. X   case FTLOWINTERFACE:
  1690. X      fprintf(f,"%u",fp->LowInterface);
  1691. X      break;
  1692. X   case FTLOWADJACENTTYPE:
  1693. X      fprintf(f,"%u",fp->LowAdjType);
  1694. X      break;
  1695. X   case FTLOWADJACENTADDRESS:
  1696. X      printaddress(f,fp->LowAdjAddress,MAC_ADDR_LEN);
  1697. X      break;
  1698. X   case FTLOWADJACENTMASK:
  1699. X      printaddress(f,fp->LowAdjMask,MAC_ADDR_LEN);
  1700. X      break;
  1701. X   case FTLOWPEERTYPE:
  1702. X      fprintf(f,"%u",fp->LowPeerType);
  1703. X      break;
  1704. X   case FTLOWPEERTYPEMASK:
  1705. X      fprintf(f,"%u",fp->LowPeerTypeMask);
  1706. X      break;
  1707. X   case FTLOWPEERADDRESS:
  1708. X      printaddress(f,fp->LowPeerAddress,PEER_ADDR_LEN);
  1709. X      break;
  1710. X   case FTLOWPEERMASK:
  1711. X      printaddress(f,fp->LowPeerMask,PEER_ADDR_LEN);
  1712. X      break;
  1713. X   case FTLOWDETAILTYPE:
  1714. X      fprintf(f,"%u",fp->LowDetailType);
  1715. X      break;
  1716. X   case FTLOWDETAILTYPEMASK:
  1717. X      fprintf(f,"%u",fp->LowDetailTypeMask);
  1718. X      break;
  1719. X   case FTLOWDETAILADDRESS:
  1720. X      printaddress(f,fp->LowDetailAddress,DETAIL_ADDR_LEN);
  1721. X      break;
  1722. X   case FTLOWDETAILMASK:
  1723. X      printaddress(f,fp->LowDetailMask,DETAIL_ADDR_LEN);
  1724. X      break;
  1725. X   case FTHIINTERFACE:
  1726. X      fprintf(f,"%u",fp->HighInterface);
  1727. X      break;
  1728. X   case FTHIADJACENTTYPE:
  1729. X      fprintf(f,"%u",fp->HighAdjType);
  1730. X      break;
  1731. X   case FTHIADJACENTADDRESS:
  1732. X      printaddress(f,fp->HighAdjAddress,MAC_ADDR_LEN);
  1733. X      break;
  1734. X   case FTHIADJACENTMASK:
  1735. X      printaddress(f,fp->HighAdjMask,MAC_ADDR_LEN);
  1736. X      break;
  1737. X   case FTHIPEERTYPE:
  1738. X      fprintf(f,"%u",fp->HighPeerType);
  1739. X      break;
  1740. X   case FTHIPEERTYPEMASK:
  1741. X      fprintf(f,"%u",fp->HighPeerTypeMask);
  1742. X      break;
  1743. X   case FTHIPEERADDRESS:
  1744. X      printaddress(f,fp->HighPeerAddress,PEER_ADDR_LEN);
  1745. X      break;
  1746. X   case FTHIPEERMASK:
  1747. X      printaddress(f,fp->HighPeerMask,PEER_ADDR_LEN);
  1748. X      break;
  1749. X   case FTHIDETAILTYPE:
  1750. X      fprintf(f,"%u",fp->HighDetailType);
  1751. X      break;
  1752. X   case FTHIDETAILTYPEMASK:
  1753. X      fprintf(f,"%u",fp->HighDetailTypeMask);
  1754. X      break;
  1755. X   case FTHIDETAILADDRESS:
  1756. X      printaddress(f,fp->HighDetailAddress,DETAIL_ADDR_LEN);
  1757. X      break;
  1758. X   case FTHIDETAILMASK:
  1759. X      printaddress(f,fp->HighDetailMask,DETAIL_ADDR_LEN);
  1760. X      break;
  1761. X   case FTRULESET:
  1762. X      fprintf(f,"%u",fp->FlowRuleSet);
  1763. X      break;
  1764. X   case FTFLOWTYPE:
  1765. X      fprintf(f,"%u",fp->FlowType);
  1766. X      break;
  1767. X   case FTUPOCTETS:
  1768. X      fprintf(f,"%lu",fp->FwdBytes);
  1769. X      break;
  1770. X   case FTUPPDUS:
  1771. X      fprintf(f,"%lu",fp->FwdPackets);
  1772. X      break;
  1773. X   case FTDOWNOCTETS:
  1774. X      fprintf(f,"%lu",fp->BackBytes);
  1775. X      break;
  1776. X   case FTDOWNPDUS:
  1777. X      fprintf(f,"%lu",fp->BackPackets);
  1778. X      break;
  1779. X   case FTFIRSTTIME:
  1780. X      fprintf(f,"%lu",fp->FirstTime);
  1781. X      break;
  1782. X   case FTLASTTIME:
  1783. X      fprintf(f,"%lu",fp->LastTime);
  1784. X      break;
  1785. X      }
  1786. X   }
  1787. X
  1788. Xunsigned short getshort(ucp)
  1789. Xunsigned char *ucp;
  1790. X{
  1791. X   return ucp[0]<<8 | ucp[1];
  1792. X   }
  1793. X
  1794. Xunsigned long getlong(ucp)
  1795. Xunsigned char *ucp;
  1796. X{
  1797. X   return ucp[0]<<24 | ucp[1]<<16 | ucp[2]<<8 | ucp[3];
  1798. X   }
  1799. X
  1800. Xunsigned short get_slice(struct meter_status *ms,
  1801. X   unsigned short first_row, unsigned char col, 
  1802. X   unsigned char first)
  1803. X{
  1804. X   int fn, row, n, r;
  1805. X   struct flow_info *fp;
  1806. X   unsigned char *ucp;
  1807. X   fn = first_row;  row = n = 0;
  1808. X   if (column_info(ms,column_blob, col,ms->OurLastCollectTime,&fn) != 0) {
  1809. X      for (r = 0, ucp = column_blob;  ; ++r) {
  1810. X         fp = &flows[row];
  1811. X         n = ntohs(getshort(ucp));  ucp += 2;  /* Flow nbr */
  1812. X         if (n < 2) break;  /* No more active flows in blob */
  1813. X         switch (col) {
  1814. X     case FTFLOWINDEX:  /* Used to synchronise column blobs */
  1815. X        break;
  1816. X     case FTFLOWSTATUS:
  1817. X            fp->FlowStatus = *ucp;
  1818. X            break;
  1819. X     case FTLOWINTERFACE:
  1820. X            fp->LowInterface = *ucp;
  1821. X            break;
  1822. X     case FTLOWADJACENTTYPE:
  1823. X            fp->LowAdjType = *ucp;
  1824. X            break;
  1825. X     case FTLOWADJACENTADDRESS:
  1826. X        bcopy(ucp,fp->LowAdjAddress,MAC_ADDR_LEN);
  1827. X        break;
  1828. X     case FTLOWADJACENTMASK:
  1829. X        bcopy(ucp,fp->LowAdjMask,MAC_ADDR_LEN);
  1830. X        break;
  1831. X     case FTLOWPEERTYPE:
  1832. X            fp->LowPeerType = *ucp;
  1833. X        break;
  1834. X     case FTLOWPEERTYPEMASK:
  1835. X            fp->LowPeerTypeMask = *ucp;
  1836. X        break;
  1837. X     case FTLOWPEERADDRESS:
  1838. X        bcopy(ucp,fp->LowPeerAddress,PEER_ADDR_LEN);
  1839. X        break;
  1840. X     case FTLOWPEERMASK:
  1841. X        bcopy(ucp,fp->LowPeerMask,PEER_ADDR_LEN);
  1842. X        break;
  1843. X     case FTLOWDETAILTYPE:
  1844. X            fp->LowDetailType = *ucp;
  1845. X        break;
  1846. X     case FTLOWDETAILTYPEMASK:
  1847. X            fp->LowDetailTypeMask = *ucp;
  1848. X        break;
  1849. X     case FTLOWDETAILADDRESS:
  1850. X        bcopy(ucp,fp->LowDetailAddress,DETAIL_ADDR_LEN);
  1851. X        break;
  1852. X     case FTLOWDETAILMASK:
  1853. X        bcopy(ucp,fp->LowDetailMask,DETAIL_ADDR_LEN);
  1854. X        break;
  1855. X     case FTHIINTERFACE:
  1856. X            fp->HighInterface = *ucp;
  1857. X            break;
  1858. X     case FTHIADJACENTTYPE:
  1859. X            fp->HighAdjType = *ucp;
  1860. X        break;
  1861. X     case FTHIADJACENTADDRESS:
  1862. X        bcopy(ucp,fp->HighAdjAddress,MAC_ADDR_LEN);
  1863. X        break;
  1864. X     case FTHIADJACENTMASK:
  1865. X        bcopy(ucp,fp->HighAdjMask,MAC_ADDR_LEN);
  1866. X        break;
  1867. X     case FTHIPEERTYPE:
  1868. X            fp->HighPeerType = *ucp;
  1869. X        break;
  1870. X     case FTHIPEERTYPEMASK:
  1871. X            fp->HighPeerTypeMask = *ucp;
  1872. X        break;
  1873. X     case FTHIPEERADDRESS:
  1874. X        bcopy(ucp,fp->HighPeerAddress,PEER_ADDR_LEN);
  1875. X        break;
  1876. X     case FTHIPEERMASK:
  1877. X        bcopy(ucp,fp->HighPeerMask,PEER_ADDR_LEN);
  1878. X        break;
  1879. X     case FTHIDETAILTYPE:
  1880. X            fp->HighDetailType = *ucp;
  1881. X        break;
  1882. X     case FTHIDETAILTYPEMASK:
  1883. X            fp->HighDetailTypeMask = *ucp;
  1884. X        break;
  1885. X     case FTHIDETAILADDRESS:
  1886. X        bcopy(ucp,fp->HighDetailAddress,DETAIL_ADDR_LEN);
  1887. X        break;
  1888. X     case FTHIDETAILMASK:
  1889. X        bcopy(ucp,fp->HighDetailMask,DETAIL_ADDR_LEN);
  1890. X        break;
  1891. X     case FTRULESET:
  1892. X            fp->FlowRuleSet = *ucp;
  1893. X        break;
  1894. X     case FTFLOWTYPE:
  1895. X            fp->FlowType = *ucp;
  1896. X        break;
  1897. X         case FTUPOCTETS:
  1898. X            fp->FwdBytes = ntohl(getlong(ucp));
  1899. X            break;
  1900. X     case FTUPPDUS:
  1901. X            fp->FwdPackets = ntohl(getlong(ucp));
  1902. X        break;
  1903. X     case FTDOWNOCTETS:
  1904. X            fp->BackBytes = ntohl(getlong(ucp));
  1905. X        break;
  1906. X     case FTDOWNPDUS:
  1907. X            fp->BackPackets = ntohl(getlong(ucp));
  1908. X        break;
  1909. X     case FTFIRSTTIME:
  1910. X            fp->FirstTime = ntohl(getlong(ucp));
  1911. X        break;
  1912. X     case FTLASTTIME:
  1913. X            fp->LastTime = ntohl(getlong(ucp));
  1914. X        break;
  1915. X        }
  1916. X         ucp += attribs[col].len;
  1917. X         if (first) {
  1918. X            fp->FlowIndex = n;  ++row;
  1919. X        }
  1920. X         else {
  1921. X            if (n == fp->FlowIndex) ++row;
  1922. X            }
  1923. X         }
  1924. X      }    
  1925. X   if (first) flows[row].FlowIndex = n;  /* Return end-of-blob marker */
  1926. X   return row;  /* Nbr of rows may decrease with later columns */
  1927. X   }
  1928. X
  1929. Xvoid monitor(ms)  /* Called every interval for each meter */
  1930. Xstruct meter_status *ms;
  1931. X{
  1932. X   time_t t;  char *ts;
  1933. X   unsigned short activeflows, first_row, nrows, r;
  1934. X   unsigned char a, col, first;
  1935. X   unsigned long aps,apb;
  1936. X   unsigned int i,j;
  1937. X   struct flow_info *fp;
  1938. X
  1939. X   time(&t);  ts = fmt_time(&t);
  1940. X   if (!(ms->status & MT_INFO)) {  /* No info */
  1941. X      if (meter_info(ms))  /* Got some */
  1942. X     ms->status |= (MT_UP | MT_INFO);
  1943. X      return;
  1944. X      }
  1945. X   if (meter_info(ms) == 0) {  /* Lost contact */
  1946. X      if (ms->status & MT_UP) {  /* Was up */
  1947. X     fprintf(log,"%s -- %s: No response\n", ts,ms->name);
  1948. X         fflush(log);  
  1949. X     if (verbose) printf("%s -- %s: No response\n", ts,ms->name);
  1950. X     }
  1951. X      ms->status &= ~MT_UP;  /* Mark as 'down' */
  1952. X      return;
  1953. X      }
  1954. X   if (!(ms->status & MT_UP)) {  /* Have contact now, was down */
  1955. X      fprintf(log,"%s -- %s: Regained contact\n", ts,ms->name);
  1956. X      fflush(log);  
  1957. X      if (verbose) printf("%s -- %s: Regained contact\n", ts,ms->name);
  1958. X      }
  1959. X   ms->status |= MT_UP;
  1960. X
  1961. X   /* Meter processing .. */
  1962. X
  1963. X   set_collect_time(ms,1);  /* Tell meter we're starti[20~ng a collection */
  1964. X
  1965. X   fprintf(ms->flows, 
  1966. X      "#Time: %s %s Flows from %lu to %lu\n",
  1967. X      ts,ms->name, ms->OurLastCollectTime,ms->uptime);
  1968. X
  1969. X   if (ms->statsreqd) {
  1970. X      if (ms->StatsTime != 0) {
  1971. X         aps = (ms->NbrPackets*10+5L)/(ms->StatsTime*10L);
  1972. X         apb = (ms->TotPktBacklog*10+5L)/(ms->StatsTime*10L);
  1973. X         }
  1974. X      else {
  1975. X         aps = apb = 0;
  1976. X         }
  1977. X      fprintf(ms->flows,"#Stats: aps=%lu apb=%lu mps=%lu mpb=%lu lsp=%lu", 
  1978. X         aps,apb, ms->MaxPktRate,ms->MaxPktBacklog, ms->LostPackets);
  1979. X      fprintf(ms->flows," avi=%u.%u mni=%u.%u",
  1980. X         ms->AvIdle1000/10,ms->AvIdle1000%10,
  1981. X         ms->MinIdle1000/10,ms->MinIdle1000%10);
  1982. X      if (ms->NbrPackets != 0)
  1983. X         i = (ms->RuleMatches*100L+5L)/(ms->NbrPackets*10L);
  1984. X      else i = 0;
  1985. X      fprintf(ms->flows," fiu=%u frc=%lu gci=%u rpp=%u.%u",
  1986. X         ms->NbrFlows,ms->FlowsRecovered,ms->GCInterval, i/10,i%10);
  1987. X      if (ms->NbrPackets != 0)
  1988. X         i = (ms->HashSearches*100L+5L)/(ms->NbrPackets*10L);
  1989. X      else i = 0;
  1990. X      if (ms->HashSearches != 0) {
  1991. X         j = (ms->HashCompares*100L+5L)/(ms->HashSearches*10L);
  1992. X         }
  1993. X      else j = 0;
  1994. X      fprintf(ms->flows," tpp=%u.%u cpt=%u.%u tts=%u tsu=%u\n",
  1995. X     i/10,i%10, j/10,j%10, ms->TotalHashSize,ms->NbrHashEntries);
  1996. X      }
  1997. X
  1998. X   if (ms->format[0] != 0) {  /* Collect flow data */
  1999. X      activeflows = 0;  first_row = 1;
  2000. X      do {
  2001. X         for (first = 1, a = 0;  (col = col_order[a]) != NULL; ++a) {
  2002. X            if (ms->required[col] == 0) continue;
  2003. X            nrows = get_slice(ms, first_row,col, first);
  2004. X            first = 0;
  2005. X            }
  2006. X         if (testing) fprintf(ms->flows,
  2007. X            "#monitor(): first_row=%u, nrows=%u, next_row=%d, end_mark=%u\n",
  2008. X               first_row, nrows, 
  2009. X               nrows != 0 ? flows[nrows-1].FlowIndex : -1,
  2010. X               flows[nrows].FlowIndex);
  2011. X         activeflows += nrows;
  2012. X         if (nrows != 0) {
  2013. X            first_row = flows[nrows-1].FlowIndex;  /* Last data row */
  2014. X            for (r = 0; r != nrows; ++r) {
  2015. X               for (col = ms->format[a = 0]; ; ) {
  2016. X                  if (col != NULL) write_attrib(ms->flows, &flows[r],col);
  2017. X                  if ((col = ms->format[a+1]) == NULL) break;
  2018. X                  fprintf(ms->flows,ms->separator[a++]);
  2019. X                  }
  2020. X               fprintf(ms->flows,"\n");
  2021. X               }
  2022. X            }
  2023. X         } while (flows[nrows].FlowIndex != 0);
  2024. X      }
  2025. X
  2026. X   fflush(ms->flows);
  2027. X   if (verbose) printf(
  2028. X      "%s %s: %d active flows from %lu to %lu\n",
  2029. X      ts,ms->name, activeflows, ms->OurLastCollectTime,ms->uptime);
  2030. X
  2031. X   ms->OurLastCollectTime = ms->uptime - 1L;
  2032. X      /* -1 to make sure we don't miss any flows.  We may
  2033. X         collect some of them twice, but we don't mind that */
  2034. X   }
  2035. X
  2036. Xvoid meter_print(FILE *f,struct meter_status *ms)
  2037. X{
  2038. X   time_t t;  char tsbuf[32];
  2039. X   struct timeval tv;
  2040. X   char buf[32];
  2041. X
  2042. X   if (!verbose) return;
  2043. X
  2044. X   time(&t);  strcpy(tsbuf,fmt_time(&t));
  2045. X   gettimeofday(&tv, (struct timezone *)0);
  2046. X   tv.tv_sec -= ms->uptime / 100;
  2047. X   if ((ms->uptime % 100)*10000 > tv.tv_usec) {
  2048. X      tv.tv_sec--;
  2049. X      tv.tv_usec += 1000000;
  2050. X      }
  2051. X   tv.tv_usec -= (ms->uptime % 100)*10000;
  2052. X   fprintf(f,"%s -- %s: %s\n\tUp %s (since %s)\n",
  2053. X      tsbuf,ms->name, ms->descr, uptime_string(ms->uptime, buf),
  2054. X      fmt_time(&tv.tv_sec));
  2055. X   }
  2056. END_OF_FILE
  2057.   if test 17129 -ne `wc -c <'netramet/src/manager/nmc.c'`; then
  2058.     echo shar: \"'netramet/src/manager/nmc.c'\" unpacked with wrong size!
  2059.   fi
  2060.   # end of 'netramet/src/manager/nmc.c'
  2061. fi
  2062. echo shar: End of archive 15 \(of 25\).
  2063. cp /dev/null ark15isdone
  2064. MISSING=""
  2065. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ; do
  2066.     if test ! -f ark${I}isdone ; then
  2067.     MISSING="${MISSING} ${I}"
  2068.     fi
  2069. done
  2070. if test "${MISSING}" = "" ; then
  2071.     echo You have unpacked all 25 archives.
  2072.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2073. else
  2074.     echo You still must unpack the following archives:
  2075.     echo "        " ${MISSING}
  2076. fi
  2077. exit 0
  2078. exit 0 # Just in case...
  2079.