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

  1. Newsgroups: comp.sources.misc
  2. From: nevil@ccu1.aukuni.ac.nz (J Nevil Brownlee)
  3. Subject: v40i105:  netramet - Network Traffic Accounting Meter, Part17/25
  4. Message-ID: <1993Nov7.221324.12419@sparky.sterling.com>
  5. X-Md4-Signature: 9de66b4a21948c06149e434851bd3fb5
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sun, 7 Nov 1993 22:13:24 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 105
  13. Archive-name: netramet/part17
  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/meter/flowhash.c netramet/src/snmplib/parse.c
  21. # Wrapped by kent@sparky on Tue Nov  2 18:17:10 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 17 (of 25)."'
  25. if test -f 'netramet/src/meter/flowhash.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'netramet/src/meter/flowhash.c'\"
  27. else
  28.   echo shar: Extracting \"'netramet/src/meter/flowhash.c'\" \(38647 characters\)
  29.   sed "s/^X//" >'netramet/src/meter/flowhash.c' <<'END_OF_FILE'
  30. X/* 1807, Mon 4 Oct 93
  31. X
  32. X   FLOWHASH.C:  AU Meter, using hash tables for tallies
  33. X
  34. X   Copyright (C) 1992,1993 by Nevil Brownlee,
  35. X   Computer Centre,  University of Auckland */
  36. X
  37. X#define DEBUG  /* Required if any of the following are set */
  38. X
  39. X#define STACK_CHECK
  40. X#define noGC_DEBUG
  41. X#define noTESTING
  42. X#define noGC_TEST1
  43. X#define noGC_TEST
  44. X#define noH_TEST
  45. X
  46. X#define noDECNET
  47. X
  48. X#include <stdio.h>
  49. X
  50. X#ifdef AU_MSDOS
  51. X#include <alloc.h>
  52. X#include <mem.h>
  53. X#ifdef DEBUG
  54. X#include <dos.h>
  55. X#endif
  56. X#endif
  57. X
  58. X#include "ausnmp.h"
  59. X
  60. X#ifdef SUNOS
  61. X#include <sys/types.h>
  62. X#include <malloc.h>
  63. X#include <string.h>
  64. X#endif
  65. X
  66. X#include "pktsnap.h"
  67. X
  68. X#define EXTFLOW
  69. X#include "flowhash.h"
  70. X#include "decnet.h"
  71. X
  72. X#ifdef DEBUG
  73. Xvoid paddr(unsigned char far *a);
  74. Xvoid daddr(unsigned char far *a);
  75. Xvoid pkey(char *msg,struct flow far *n);
  76. X#endif
  77. X
  78. XFILE *log;
  79. X
  80. X#define FBLKSZ 425
  81. X
  82. Xstruct flow far *fl INIT(NULL);
  83. Xstruct flow far *fa;  int nf_flows INIT(0);
  84. X
  85. Xstruct flow far *get_flow(void)  /* Get an unused flow */
  86. X{
  87. X   struct flow far *q;
  88. X   if (fl != NULL) {
  89. X      q = fl;  fl = fl->link.next;
  90. X      }
  91. X   else {
  92. X      if (nf_flows == 0) {
  93. X     fa = (struct flow far *)farmalloc(sizeof(struct flow)*FBLKSZ);
  94. X     if (fa == NULL) {
  95. X        scpos(0,24);  printf("No memory for new flows!");
  96. X        return NULL;
  97. X        }
  98. X     nf_flows = FBLKSZ-1;
  99. X     }
  100. X      else {
  101. X     ++fa;  --nf_flows;
  102. X     }
  103. X#ifdef GC_DEBUG
  104. Xscpos(0,24);  printf("\nfa=%Fp, nff=%d, empty_ix=%u\n",fa,nf_flows,empty_ix);
  105. X#endif
  106. X      q = fa;
  107. X      }
  108. X   return q;
  109. X   }
  110. X
  111. Xvoid free_flow(struct flow far *q)  /* Return a flow to free list */
  112. X{
  113. X#ifdef GC_DEBUG
  114. Xscpos(0,24);  printf("\nfree_flow(%Fp), empty_ix=%u\n", q,empty_ix);
  115. X#endif
  116. X   q->link.next = fl;
  117. X   fl = q;
  118. X   }
  119. X
  120. X#ifdef DEBUG
  121. Xint log_nbr = 1;
  122. X
  123. Xvoid open_log()
  124. X{
  125. X   char fn[30];
  126. X   sprintf(fn,"flows.%03d",log_nbr++);
  127. X   log = fopen(fn, "w");
  128. X   }
  129. X
  130. Xvoid paddr(a)
  131. Xunsigned char far *a;
  132. X{
  133. X   fprintf(log,"%u.%u.%u.%u", a[0],a[1],a[2],a[3]);
  134. X   }
  135. X
  136. Xvoid daddr(a)
  137. Xunsigned char far *a;
  138. X{
  139. X/*   printf("%u.%u.%u.%u", a[0],a[1],a[2],a[3]);  @@@ */
  140. X   printf("%02x-%02x-%02x-%02x-%02x-%02x", a[0],a[1],a[2],a[3],a[4],a[5]);
  141. X   }
  142. X
  143. Xvoid pkey(msg,f)
  144. Xchar *msg;
  145. Xstruct flow far *f;
  146. X{
  147. X   if (!log) open_log();
  148. X   fprintf(log,"%s: %Fp  %u %u\n   {", msg,f, f->FlowType,f->PeerAddrType);
  149. X   paddr(f->Low.PeerAddress); fprintf(log," & ");
  150. X   paddr(f->Low.PeerMask); fprintf(log,"} -> {");
  151. X   paddr(f->High.PeerAddress); fprintf(log," & ");
  152. X   paddr(f->High.PeerMask); fprintf(log,"}\n");
  153. X   }
  154. X#endif
  155. X
  156. X#define DRT_SIZE  5
  157. Xstruct rule default_rule_table[DRT_SIZE] = {
  158. X/* Selector,        Mask,          Value,                Action, JumpIndex */
  159. X   {FTLOWPEERTYPE, 255,0,0,0,0,0, AT_IP,0,0,0,0,0,        RA_AGGREGATE, 1},  /* 1 */
  160. X   {FTLOWPEERTYPE, 255,0,0,0,0,0, AT_NOVELL,0,0,0,0,0,    RA_AGGREGATE, 2},  /* 2 */
  161. X   {FTLOWPEERTYPE, 255,0,0,0,0,0, AT_DECNET,0,0,0,0,0,    RA_AGGREGATE, 3},  /* 3 */
  162. X   {FTLOWPEERTYPE, 255,0,0,0,0,0, AT_ETHERTALK,0,0,0,0,0, RA_AGGREGATE, 4},  /* 4 */
  163. X   {FTLOWPEERADDRESS, 0,0,0,0,0,0,   0,0,0,0,0,0,         RA_SUCCEED,   0} };
  164. X
  165. X#define DAT_SIZE  4
  166. Xstruct flow default_action_table[DAT_SIZE] = {
  167. X   {NULL, 0L,0L,0L,0L, 0L,0L, 1,FT_AGGREGATE,  AT_IP,255, 0,0,        /* 1 */
  168. X      {0,0,0,0,0,0, 0,0,0,0,0,0, 11,12,0,0, 255,255,0,0, 0,0, 0,0},
  169. X      {0,0,0,0,0,0, 0,0,0,0,0,0, 13,14,0,0, 255,255,0,0, 0,0, 0,0} },
  170. X   {NULL, 0L,0L,0L,0L, 0L,0L, 1,FT_AGGREGATE,  AT_NOVELL,255, 0,0,    /* 2 */
  171. X      {0,0,0,0,0,0, 0,0,0,0,0,0, 21,22,0,0, 255,255,0,0, 0,0, 0,0},
  172. X      {0,0,0,0,0,0, 0,0,0,0,0,0, 23,24,0,0, 255,255,0,0, 0,0, 0,0} },
  173. X   {NULL, 0L,0L,0L,0L, 0L,0L, 1,FT_AGGREGATE,  AT_DECNET,255, 0,0,    /* 3 */
  174. X      {0,0,0,0,0,0, 0,0,0,0,0,0, 31,32,0,0, 255,255,0,0, 0,0, 0,0},
  175. X      {0,0,0,0,0,0, 0,0,0,0,0,0, 33,34,0,0, 255,255,0,0, 0,0, 0,0} },
  176. X   {NULL, 0L,0L,0L,0L, 0L,0L, 1,FT_AGGREGATE,  AT_ETHERTALK,255, 0,0, /* 4 */
  177. X      {0,0,0,0,0,0, 0,0,0,0,0,0, 41,42,0,0, 255,255,0,0, 0,0, 0,0},
  178. X      {0,0,0,0,0,0, 0,0,0,0,0,0, 43,34,0,0, 255,255,0,0, 0,0, 0,0} } };
  179. X
  180. Xvoid init_flow(struct flow far *f, unsigned char type)
  181. X{
  182. X   f->UpOctets = f->UpPDUs = f->DownOctets = f->DownPDUs = f->LastTime = 0L;
  183. X   f->FirstTime = s_uptime;  /* Initialise flow */
  184. X   f->FlowType = type;  f->FlowRuleSet = CurrentRuleSet;
  185. X   f->link.next = NULL;
  186. X   }
  187. X
  188. Xvoid optimise_rule_table()
  189. X{
  190. X   unsigned int j, k, g, h, x, l,
  191. X      nht,  /* Nbr of rule_hash_tbls */
  192. X      ths,  /* Sum of rule_hash_tbl sizes */
  193. X      rhss;  /* Total rule_hash sequence size */
  194. X   struct rule far *rp, far *hp;
  195. X   struct rule_hash_tbl far *c_rh;
  196. X   unsigned char hash;
  197. X
  198. X   hp = &c_rt[0];  hp->hash_tbl_index = 1;
  199. X   for (j = 1;  j != c_rsz;  ++j) {  /* Mark match break points */
  200. X      rp = &c_rt[j];
  201. X      rp->hash_tbl_index = rp->RuleSelector != hp->RuleSelector ||
  202. X        qcmp(rp->RuleMask,hp->RuleMask,RULE_ADDR_LEN) != 0;
  203. X      hp = rp;
  204. X      }
  205. X   for (j = 0;  j != c_rsz;  ++j) {  /* Mark goto break points */
  206. X      rp = &c_rt[j];  rp->hash_link = 0;
  207. X      k = rp->RuleAction;
  208. X      if (k == RA_PUSHTO || k == RA_POPTO || k == RA_GOTO) {
  209. X     hp = &c_rt[rp->RuleJumpIndex-1];
  210. X     hp->hash_tbl_index = 2;
  211. X     }
  212. X      }
  213. X#ifdef H_TEST
  214. X   scpos(0,24);  printf("rule  index  link  MARKED\n");
  215. X   for (j = 0;  j != c_rsz;  ++j) {
  216. X      rp = &c_rt[j];
  217. X      printf("%3d %5d %5d\n", j, rp->hash_tbl_index,rp->hash_link);
  218. X      }
  219. X#endif
  220. X   nht = ths = 0;
  221. X   hp = &c_rt[0];  k = 1;
  222. X   for (j = 1;  j != c_rsz;  ++j) {  /* Find compare groups */
  223. X      rp = &c_rt[j];
  224. X      if ((g = rp->hash_tbl_index) == 0) ++k;  /* Same group */
  225. X      if (g != 0 || j == c_rsz-1) {  /* End of a group */
  226. X     if (k >= MNCGRPSZ && hp->RuleSelector != RS_NULL) {
  227. X        for (h = 2; h <= k; h <<= 1) ;  /* h = next power of 2 */
  228. X        if (h > 256) h = 256;
  229. X        hp->hash_tbl_index = k;  /* Remember group and */
  230. X        hp->hash_link = h;       /*   hash table sizes */
  231. X        ++nht;  ths += h;
  232. X        }
  233. X     else hp->hash_tbl_index = 0;
  234. X     hp = rp;  k = 1;
  235. X     }
  236. X      rp->hash_tbl_index = 0;  /* Last row can't start a group */
  237. X      }
  238. X   rhss = 1 + nht*2 + ths;  /* rule_hash set size (ints) */
  239. X   if (rh_size < rhss) rule_hash =
  240. X      (int far *)farmalloc(sizeof(int)*(rh_size = rhss));
  241. X#ifdef H_TEST
  242. X   printf("rule  index  link  GROUPED\n");
  243. X   for (j = 0;  j != c_rsz;  ++j) {
  244. X      rp = &c_rt[j];
  245. X      printf("%3d %5d %5d\n", j, rp->hash_tbl_index,rp->hash_link);
  246. X      }
  247. X#endif
  248. X   rule_hash[0] = 0;  k = 1;  rp = &c_rt[j = 0];
  249. X   for ( ; nht != 0; --nht, k += 2+h) {
  250. X      c_rh = (struct rule_hash_tbl far *)&rule_hash[k];
  251. X      while (rp->hash_tbl_index == 0) {
  252. X     ++rp; ++j;
  253. X     }
  254. X      g = rp->hash_tbl_index;  /* Group size */
  255. X      h = rp->hash_link;  /* Hash table size */
  256. X      rp->hash_tbl_index = k;  /* Index of hash_tbl in rule_hash */
  257. X      rp->hash_link = 0;
  258. X      c_rh->group_last = j+g;
  259. X      c_rh->hash_mask = h-1;
  260. X      for (x = 0; x != h; ++x) c_rh->hash_ent[x] = 0;
  261. X      for ( ; g != 0; --g) {
  262. X     for (hash = x = 0; x != RULE_ADDR_LEN; ++x)
  263. X        hash += rp->RuleMatchedValue[x] & rp->RuleMask[x];
  264. X     hash &= h-1;
  265. X     if ((l = c_rh->hash_ent[hash]) == 0)
  266. X        c_rh->hash_ent[hash] = j+1;  /* First rule with this hash */
  267. X     else {
  268. X        do {
  269. X           hp = &c_rt[l-1];  l = hp->hash_link;
  270. X           } while (l != 0);
  271. X        hp->hash_link = j+1;  /* Add to end of hash chain */
  272. X        }
  273. X     ++rp; ++j;
  274. X     }
  275. X      }
  276. X#ifdef H_TEST
  277. X   printf("rule  index  link  HASHED\n");
  278. X   for (j = 0;  j != c_rsz;  ++j) {
  279. X      rp = &c_rt[j];
  280. X      printf("%3d %5d %5d\n", j, rp->hash_tbl_index,rp->hash_link);
  281. X      }
  282. X   printf("rule_hash . . .\n");
  283. X   for (j = 0;  j != rhss;  ++j) printf("%d ",rule_hash[j]);
  284. X   printf("\n");
  285. X#endif
  286. X   }
  287. X
  288. Xint open_rule_set(unsigned char doSet, unsigned char n)
  289. X{
  290. X   unsigned int j;
  291. X   struct rule far *rp;
  292. X   if (rt_size[n-1] == 0) return 0;  /* Incomplete tables */
  293. X   if (doSet) {
  294. X      c_rt = rule_table[n-1];  c_rsz = rt_size[n-1];
  295. X      for (j = 0; j != c_rsz; ++j) {
  296. X     rp = &c_rt[j];
  297. X     if (rp->RuleAction == RA_COUNT) rp->RuleJumpIndex = 0;
  298. X     }
  299. X      c_at = action_table[n-1];  c_asz = at_size[n-1];
  300. X      CurrentRuleSet = n;
  301. X      for (j = 0; j != c_asz; ++j) init_flow(&c_at[j],FT_RULE);
  302. X      optimise_rule_table();
  303. X      }
  304. X
  305. X   return 1;
  306. X   }
  307. X
  308. Xvoid close_rule_set(void)
  309. X{
  310. X   unsigned int j,k;
  311. X   struct rule far *rp;
  312. X   struct flow far *fp, far *ap, far *lfp;
  313. X   struct hash_tbl far *ht;
  314. X   struct flow far * far *sf;
  315. X   for (j = 0; j != c_rsz; ++j) {
  316. X      rp = &c_rt[j];
  317. X      switch (rp->RuleAction) {
  318. X      case RA_COUNT:
  319. X     if (rp->RuleJumpIndex != 0) {
  320. X        fp = find_flow(rp->RuleJumpIndex);
  321. X        fp->link.count = NULL;
  322. X        }
  323. X     rp->RuleJumpIndex = 0;
  324. X     break;
  325. X      case RA_TALLY:
  326. X     ap = &c_at[rp->RuleJumpIndex-1];
  327. X     if ((ht = ap->link.hash) != NULL) {
  328. X        for (k = 0; k != HASHMOD; ++k) {
  329. X           sf = &ht->hash_ent[k];  /* Address of hash table entry */
  330. X           if ((fp = sf[0]) != NULL) {
  331. X          do {
  332. X             lfp = fp;  fp = lfp->link.next;
  333. X             lfp->link.next = NULL;
  334. X             } while (fp != (struct flow far *)sf);
  335. X          --n_hash_ents;
  336. X          }
  337. X           }
  338. X        farfree(ht);
  339. X        --n_hash_tables;  t_hash_size -= HASHMOD;
  340. X        ap->link.hash = NULL;
  341. X        }
  342. X     break;
  343. X      case RA_AGGREGATE:
  344. X     ap = &c_at[rp->RuleJumpIndex-1];
  345. X     if ((fp = ap->link.action) != NULL) {
  346. X        fp->link.action = NULL;
  347. X        ap->link.action = NULL;
  348. X        }
  349. X     break;
  350. X     }
  351. X      }
  352. X   }
  353. X
  354. X#ifdef GC_DEBUG
  355. Xint dup_flow(struct flow far *f, char *msg)
  356. X{
  357. X   int x;
  358. X   for (x = 253; x <= mxflowsp1; ++x)
  359. X      if (flow_ix[x-1] != NULL) {
  360. X     scpos(0,24);
  361. X     printf("   flow_ix[%d]=%Fp !!\n", x,flow_ix[x-1]);
  362. X     }
  363. X   for (x = 2; x <= mxflowsp1; ++x)
  364. X      if (flow_ix[x-1] == f) {
  365. X     scpos(0,24);
  366. X     printf("Flow %Fp is flow_ix[%d], msg=%s\n", f,x, msg);
  367. X     exit(0);
  368. X     }
  369. X   return 0;
  370. X   }
  371. X#endif
  372. X
  373. Xunsigned int number_flow(struct flow far *fp)  /* Allocate a flow_nbr */
  374. X{
  375. X   unsigned int start_ix = empty_ix;
  376. X   do {
  377. X      if (++empty_ix > mxflowsp1)  /* empty_ix goes from 2 to MXFLOWS+1 */
  378. X     empty_ix = 2;  /* Flow 1 is a dummy for snmp */
  379. X      if (flow_ix[empty_ix-1] == NULL) {
  380. X     ++nflows;  /* Nbr of active accounting flows */
  381. X     flow_ix[empty_ix-1] = fp;
  382. X#ifdef GC_DEBUG
  383. X     printf("nbr_flow(%Fp) -> %u\n", fp,empty_ix);
  384. X#endif
  385. X     return empty_ix;  /* 1-org */
  386. X     }
  387. X      } while (empty_ix != start_ix);
  388. X   scpos(0,24);  printf("Too many flows");
  389. X   bkgi = 1;  /* Kick background process: get busy on garbage collecting! */
  390. X   return NULL;
  391. X   }
  392. X
  393. Xstruct flow far *find_flow(int x)  /* Find flow with flow_nbr x */
  394. X{
  395. X   if (x > mxflowsp1 || x < 2) {
  396. X      display_msg(1,"Invalid flow number!");
  397. X      return NULL;
  398. X      }
  399. X   return flow_ix[x-1];
  400. X   }
  401. X
  402. Xvoid garbage_collect()
  403. X{
  404. X   unsigned char e = gc_e, f = gc_f;   
  405. X   struct rule far *rp;
  406. X   struct flow far *fp, far *np, far *tp, far *ltp;
  407. X#ifdef GC_DEBUG
  408. X   int k;
  409. X#endif
  410. X#ifdef GC_TEST1
  411. X   scpos(0,24);
  412. X   printf("GC: gctime=%lu, gcf_ix=%u, e=%d, f=%d\n",
  413. X      GarbageCollectTime,gcf_ix,e,f);
  414. X#endif
  415. X   for (;;) {
  416. X      if (++gcf_ix > mxflowsp1)  /* gcf_ix goes from 2 to MXFLOWS+1 */
  417. X     gcf_ix = 2;  /* Flow 1 is a dummy for snmp */
  418. X      if ((fp = flow_ix[gcf_ix-1]) == NULL) {  /* Unused flow index */
  419. X         if (--e == 0) return;
  420. X         continue;
  421. X         }
  422. X      if (fp->LastTime <= GarbageCollectTime) {  /* OK, recover it */
  423. X#ifdef GC_TEST1
  424. X      printf("   f=%d, gcf_ix=%d, LastTime=%lu\n",
  425. X     f,gcf_ix,fp->LastTime);
  426. X#endif
  427. X     if (fp->link.next != NULL) {  /* Not an orphaned flow */
  428. X#ifdef GC_DEBUG
  429. X        scpos(0,24);
  430. X        printf("GC: typ=%u, set=%u, ix=%u, fp=%Fp, np=%Fp\n",
  431. X           fp->FlowType,fp->FlowRuleSet,gcf_ix, fp,fp->link.next);
  432. X        k = 0;
  433. X#endif
  434. X        switch(fp->FlowType) {
  435. X        case FT_COUNT:
  436. X           rp = fp->link.count;
  437. X           rp->RuleJumpIndex = 0;
  438. X           break;
  439. X        case FT_TALLY:
  440. X           np = fp->link.next;
  441. X           tp = fp;  do {
  442. X          ltp = tp;
  443. X#ifdef GC_DEBUG
  444. Xprintf("   k=%d, ltp=%Fp, tp=%Fp\n", ++k, ltp,ltp->link.next);
  445. Xif (tp->link.next == NULL || k > 10) exit(0);  /* Infinite loop - stop */
  446. X#endif
  447. X          } while ((tp = tp->link.next) != fp);
  448. X           ltp->link.next = ltp == np ? NULL : np;
  449. X           break;
  450. X        case FT_AGGREGATE:
  451. X           tp = fp->link.action;
  452. X           tp->link.action = NULL;
  453. X           break;
  454. X               }
  455. X        }
  456. X     flow_ix[gcf_ix-1] = NULL;
  457. X#ifdef GC_DEBUG
  458. X      printf("\ngarbage_collect ..\n");
  459. X#endif
  460. X     free_flow(fp);
  461. X     --nflows;
  462. X     ++FlowsRecovered;
  463. X#ifdef GC_TEST
  464. X      scpos(0,24);
  465. X      printf("Flow %d (type %d) recovered\n", gcf_ix,fp->FlowType);
  466. X#endif
  467. X     }
  468. X      if (--f == 0) return;
  469. X      }
  470. X   }
  471. X
  472. Xstruct flow far *data;  /* Work space for building target flows */
  473. Xstruct flow far *tally;
  474. X
  475. Xunsigned int p_stack[RSTKSIZ];  /* Pattern stack */
  476. Xint p_s_depth;
  477. X
  478. X#ifdef GC_DEBUG
  479. Xvoid print_chain(struct hash_tbl far *t, unsigned char hash, char *msg)
  480. X{
  481. X   struct flow far * far *sf;
  482. X   struct flow far *f, far *lf;
  483. X   sf = &t->hash_ent[hash];  /* Address of hash table entry */
  484. X   scpos(0,24);  printf("Chain: t=%Fp, hash=%u, sf=%Fp, msg=%s\n",
  485. X      t,hash,sf, msg);
  486. X   lf = f = sf[0];
  487. X   do {
  488. X      printf("   f=%Fp\n", f);
  489. X      if ((lf = f) == NULL) return;
  490. X      } while ((f = lf->link.next) != (struct flow far *)sf);
  491. X   }
  492. X#endif
  493. X
  494. Xstruct flow far *search_hash_table(
  495. X   struct hash_tbl far *t,  /* Table to search */
  496. X   struct key far *Low,  /* Target keys */
  497. X   struct key far *High,
  498. X   struct flow far *pdu,
  499. X   struct flow far *ap,  /* Action with table's masks */
  500. X   unsigned char OK_to_add  /* 1 = add new flow if not found */
  501. X   )
  502. X{
  503. X   struct flow far * far *sf;
  504. X   struct flow far *f, far *lf;
  505. X   struct rule far *rp;
  506. X   unsigned char hash, k, t_PeerType, t_DetailType,
  507. X      t_LowAdj,t_HighAdj, t_LowPeer,t_HighPeer, t_LowDetail,t_HighDetail;
  508. X   t_PeerType = t_DetailType = t_LowAdj = t_HighAdj = 
  509. X      t_LowPeer = t_HighPeer = t_LowDetail = t_HighDetail = hash = 0;
  510. X   ++n_hash_searches;
  511. X   bcopy((unsigned char far *)Key(ap),  /* Copy action entry into tally */
  512. X      (unsigned char far *)Key(tally), sizeof(struct flow_key));
  513. X   if (qcmp(tally->Low.PeerMask,null_flow->Low.PeerMask,PEER_ADDR_LEN) != 0) {
  514. X      t_LowPeer = 1;  /* Tally this field */
  515. X      for (k = 0; k != PEER_ADDR_LEN; ++k)
  516. X     hash += (tally->Low.PeerAddress[k] =
  517. X        Low->PeerAddress[k] & tally->Low.PeerMask[k]);
  518. X      }
  519. X   if (qcmp(tally->High.PeerMask,null_flow->High.PeerMask,PEER_ADDR_LEN) != 0) {
  520. X      t_HighPeer = 1;  /* Tally this field */
  521. X      for (k = 0; k != PEER_ADDR_LEN; ++k)
  522. X     hash += (tally->High.PeerAddress[k] =
  523. X        High->PeerAddress[k] & tally->High.PeerMask[k]);
  524. X      }
  525. X   if (tally->DetailTypeMask != 0) {
  526. X      t_DetailType = 1;  /* Tally this field */
  527. X      hash += (tally->DetailAddrType =
  528. X     pdu->DetailAddrType & tally->DetailTypeMask);
  529. X      }
  530. X   if (qcmp(tally->Low.DetailMask,null_flow->Low.DetailMask,DETAIL_ADDR_LEN) != 0) {
  531. X      t_LowDetail = 1;  /* Tally this field */
  532. X      for (k = 0; k != DETAIL_ADDR_LEN; ++k)
  533. X     hash += (tally->Low.DetailAddress[k] =
  534. X        Low->DetailAddress[k] & tally->Low.DetailMask[k]);
  535. X      }
  536. X   if (qcmp(tally->High.DetailMask,null_flow->High.DetailMask,DETAIL_ADDR_LEN) != 0) {
  537. X      t_HighDetail = 1;  /* Tally this field */
  538. X      for (k = 0; k != DETAIL_ADDR_LEN; ++k)
  539. X     hash += (tally->High.DetailAddress[k] =
  540. X        High->DetailAddress[k] & tally->High.DetailMask[k]);
  541. X      }
  542. X   if (qcmp(tally->Low.AdjMask,null_flow->Low.AdjMask,MAC_ADDR_LEN) != 0) {
  543. X      t_LowAdj = 1;  /* Tally this field */
  544. X      for (k = 0; k != MAC_ADDR_LEN; ++k)
  545. X     hash += (tally->Low.AdjAddress[k] =
  546. X        Low->AdjAddress[k] & tally->Low.AdjMask[k]);
  547. X      }
  548. X   if (qcmp(tally->High.AdjMask,null_flow->High.AdjMask,MAC_ADDR_LEN) != 0) {
  549. X      t_HighAdj = 1;  /* Tally this field */
  550. X      for (k = 0; k != MAC_ADDR_LEN; ++k)
  551. X     hash += (tally->High.AdjAddress[k] =
  552. X        High->AdjAddress[k] & tally->High.AdjMask[k]);
  553. X      }
  554. X   if (tally->PeerTypeMask != 0) {
  555. X      t_PeerType = 1;  /* Tally this field */
  556. X      hash += (tally->PeerAddrType =
  557. X     pdu->PeerAddrType & tally->PeerTypeMask);
  558. X      }
  559. X
  560. X   sf = &t->hash_ent[hash];  /* Address of hash table entry */
  561. X#ifdef TESTING
  562. Xif (!log) open_log();
  563. Xfprintf(log,"Search_hash(): add=%d, lo=%d, hi=%d, hash=%d\n   LowPeer=",
  564. X   OK_to_add, t_LowPeer,t_HighPeer, hash);
  565. Xpaddr(tally->Low.PeerAddress); fprintf(log,", HighPeer=");
  566. Xpaddr(tally->High.PeerAddress);
  567. Xfprintf(log,"\n   sf=%Fp, sf[0]=%Fp\n", sf,sf[0]);
  568. X#endif
  569. X   if ((f = sf[0]) == NULL) {
  570. X      lf = NULL;  /* Empty hash chain */
  571. X      ++n_hash_compares;  /* Make sure compares >= searches! */
  572. X      }
  573. X   else {
  574. X      do {
  575. X#ifdef GC_DEBUG
  576. X     if (f == NULL) {
  577. X        print_chain(t,hash,"existing");
  578. X        exit(0);
  579. X        }
  580. X#endif
  581. X     ++n_hash_compares;
  582. X     for (;;) {
  583. X        if (t_LowPeer && qcmp(tally->Low.PeerAddress,
  584. X           f->Low.PeerAddress,PEER_ADDR_LEN) != 0) break;
  585. X        if (t_HighPeer && qcmp(tally->High.PeerAddress,
  586. X           f->High.PeerAddress,PEER_ADDR_LEN) != 0) break;
  587. X        if (t_DetailType && 
  588. X           tally->DetailAddrType != f->DetailAddrType) break;
  589. X        if (t_LowDetail && qcmp(tally->Low.DetailAddress,
  590. X           f->Low.DetailAddress,DETAIL_ADDR_LEN) != 0) break;
  591. X        if (t_HighDetail && qcmp(tally->High.DetailAddress,
  592. X           f->High.DetailAddress,DETAIL_ADDR_LEN) != 0) break;
  593. X         if (t_LowAdj && qcmp(tally->Low.AdjAddress,
  594. X           f->Low.AdjAddress,MAC_ADDR_LEN) != 0) break;
  595. X        if (t_HighAdj && qcmp(tally->High.AdjAddress,
  596. X           f->High.AdjAddress,MAC_ADDR_LEN) != 0) break;
  597. X        if (t_PeerType && 
  598. X           tally->PeerAddrType != f->PeerAddrType) break;
  599. X        return f;  /* Matched */
  600. X        }
  601. X     lf = f;
  602. X     } while ((f = lf->link.next) != (struct flow far *)sf);
  603. X      f = NULL;  /* Loop stops with lf -> last flow in chain */
  604. X      }
  605. X#ifdef TESTING
  606. Xfprintf(log,"   after search: f=%Fp, lf=%Fp, sf=%Fp, sf[0]=%Fp\n",
  607. X   f, lf, sf, sf[0]);
  608. X#endif
  609. X   if (OK_to_add) {
  610. X      if ((f = get_flow()) == NULL)  /* Build new tally flow */
  611. X     return NULL;  /* Out of memory */
  612. X      bcopy((unsigned char far *)Key(tally),  /* bcopy (s,d,n) */
  613. X     (unsigned char far *)Key(f), sizeof(struct flow_key));
  614. X      init_flow(f,FT_TALLY);
  615. X      if (number_flow(f) == NULL) {  /* No room in flow_index */
  616. X     free_flow(f);  return NULL;
  617. X     }
  618. X      f->link.next = (struct flow far *)sf;
  619. X#ifdef GC_DEBUG
  620. X      if (f->link.next == NULL) {
  621. X     print_chain(t,hash,"adding new flow");
  622. X     exit(0);
  623. X     }
  624. X#endif
  625. X      if (lf == NULL) {  /* Empty hash chain */
  626. X     sf[0] = f;  ++n_hash_ents;
  627. X     }
  628. X      else lf->link.next = f;
  629. X#ifdef TESTING
  630. Xfprintf(log,"   flow %d added, addr=%Fp\n", empty_ix,f);
  631. X#endif
  632. X      }
  633. X   return f;
  634. X   }
  635. X
  636. Xunsigned char masked_value[RULE_ADDR_LEN];
  637. X
  638. Xunsigned char mk_hash(
  639. X   unsigned char far *vp, unsigned char far *mp, unsigned char n)
  640. X{
  641. X   unsigned char hash,j;
  642. X   for (hash = j = 0;  j != n;  ++j)
  643. X      hash += (masked_value[j] = vp[j] & mp[j]);
  644. X   return hash;
  645. X   }
  646. X
  647. Xint pkt_match(  /* 0 = failed to match, 1 = matched, */
  648. X        /*    2 = matched but flow not yet in tally */
  649. X   unsigned char forward,  /* 0 => from & to have been swapped */
  650. X   unsigned char OK_to_add,
  651. X   int len,  /* Octets in PDU */
  652. X   struct flow far *pdu, struct key far *from, struct key far *to)
  653. X{
  654. X   unsigned int rx, j, f;
  655. X   struct rule far *rp;
  656. X   unsigned char match, hash;
  657. X   struct flow far *fp, far *ap;
  658. X   struct rule_hash_tbl far *c_rh;
  659. X   struct hash_tbl far *ht;
  660. X
  661. X   p_s_depth = 0;
  662. X   for (rx = 1; rx <= c_rsz; ) {  /* Search the rule table */
  663. X      rp = &c_rt[rx-1];
  664. X      ++n_matches;
  665. X      if (rp->hash_tbl_index == 0) {  /* Simple compare */
  666. X     switch (rp->RuleSelector) {
  667. X     case FTLOWPEERADDRESS:
  668. X        for (j = 0;  j != PEER_ADDR_LEN;  ++j) {
  669. X           if ((from->PeerAddress[j] & rp->RuleMask[j]) !=
  670. X          rp->RuleMatchedValue[j]) break;
  671. X           }
  672. X        match = j == PEER_ADDR_LEN;
  673. X        break;
  674. X     case FTHIPEERADDRESS:
  675. X        for (j = 0;  j != PEER_ADDR_LEN;  ++j) {
  676. X           if ((to->PeerAddress[j] & rp->RuleMask[j]) !=
  677. X          rp->RuleMatchedValue[j]) break;
  678. X           }
  679. X        match = j == PEER_ADDR_LEN;
  680. X        break;
  681. X     case FTLOWPEERTYPE:
  682. X     case FTHIPEERTYPE:
  683. X        match = pdu->PeerAddrType == rp->RuleMatchedValue[0];
  684. X        break;
  685. X     case FTLOWDETAILADDRESS:
  686. X        for (j = 0;  j != DETAIL_ADDR_LEN;  ++j) {
  687. X           if ((from->DetailAddress[j] & rp->RuleMask[j]) !=
  688. X          rp->RuleMatchedValue[j]) break;
  689. X           }
  690. X        match = j == DETAIL_ADDR_LEN;
  691. X        break;
  692. X     case FTHIDETAILADDRESS:
  693. X        for (j = 0;  j != DETAIL_ADDR_LEN;  ++j) {
  694. X           if ((to->DetailAddress[j] & rp->RuleMask[j]) !=
  695. X          rp->RuleMatchedValue[j]) break;
  696. X           }
  697. X        match = j == DETAIL_ADDR_LEN;
  698. X        break;
  699. X     case FTLOWDETAILTYPE:
  700. X     case FTHIDETAILTYPE:
  701. X        match = pdu->DetailAddrType == rp->RuleMatchedValue[0];
  702. X        break;
  703. X     case FTLOWADJACENTADDRESS:
  704. X        for (j = 0;  j != MAC_ADDR_LEN;  ++j) {
  705. X           if ((from->AdjAddress[j] & rp->RuleMask[j]) !=
  706. X          rp->RuleMatchedValue[j]) break;
  707. X           }
  708. X        match = j == MAC_ADDR_LEN;
  709. X        break;
  710. X     case FTHIADJACENTADDRESS:
  711. X        for (j = 0;  j != MAC_ADDR_LEN;  ++j) {
  712. X           if ((to->AdjAddress[j] & rp->RuleMask[j]) !=
  713. X          rp->RuleMatchedValue[j]) break;
  714. X           }
  715. X        match = j == MAC_ADDR_LEN;
  716. X        break;
  717. X     case RS_NULL:
  718. X        match = 1;  /* Don't test anything */
  719. X        break;
  720. X     default:
  721. X        match = 0;
  722. X        }
  723. X     }
  724. X      else {  /* Hashed compare */
  725. X     switch (rp->RuleSelector) {
  726. X     case FTLOWPEERADDRESS:
  727. X        hash = mk_hash(from->PeerAddress,rp->RuleMask,RULE_ADDR_LEN);
  728. X        break;
  729. X     case FTHIPEERADDRESS:
  730. X        hash = mk_hash(to->PeerAddress,rp->RuleMask,RULE_ADDR_LEN);
  731. X        break;
  732. X     case FTLOWPEERTYPE:
  733. X     case FTHIPEERTYPE:
  734. X        hash = mk_hash(&pdu->PeerAddrType,rp->RuleMask,RULE_ADDR_LEN);
  735. X        break;
  736. X     case FTLOWDETAILADDRESS:
  737. X        hash = mk_hash(from->DetailAddress,rp->RuleMask,RULE_ADDR_LEN);
  738. X        break;
  739. X     case FTHIDETAILADDRESS:
  740. X        hash = mk_hash(to->DetailAddress,rp->RuleMask,RULE_ADDR_LEN);
  741. X        break;
  742. X     case FTLOWDETAILTYPE:
  743. X     case FTHIDETAILTYPE:
  744. X        hash = mk_hash(&pdu->DetailAddrType,rp->RuleMask,RULE_ADDR_LEN);
  745. X        break;
  746. X     case FTLOWADJACENTADDRESS:
  747. X        hash = mk_hash(from->AdjAddress,rp->RuleMask,RULE_ADDR_LEN);
  748. X        break;
  749. X     case FTHIADJACENTADDRESS:
  750. X        hash = mk_hash(to->AdjAddress,rp->RuleMask,RULE_ADDR_LEN);
  751. X        break;
  752. X        }
  753. X     c_rh = (struct rule_hash_tbl far *)&rule_hash[rp->hash_tbl_index];
  754. X     hash &= c_rh->hash_mask;  match = 0;
  755. X     if ((rx = c_rh->hash_ent[hash]) != 0) {
  756. X        do {
  757. X           rp = &c_rt[rx-1];
  758. X           if (qcmp((unsigned char far *)masked_value,
  759. X             rp->RuleMatchedValue, RULE_ADDR_LEN) == 0) {
  760. X          match = 1;  break;  /* Matched */
  761. X          }
  762. X           } while ((rx = rp->hash_link) != 0);
  763. X        }
  764. X     if (match == 0) rx = c_rh->group_last;  /* Not in group */
  765. X     }
  766. X      if (match) {
  767. X     switch (rp->RuleAction) {
  768. X     case RA_COUNT:
  769. X        p_stack[p_s_depth++] = rx;  /* Remember last matched rule */
  770. X        if ((j = rp->RuleJumpIndex) == 0) {
  771. X           if ((fp = get_flow()) == NULL)
  772. X          return 1;  /* Out of memory: don't try match again */
  773. X           bcopy((unsigned char far *)Key(null_flow),  /* bcopy (s,d,n) */
  774. X          (unsigned char far *)Key(fp), sizeof(struct flow_key));
  775. X           for (j = 0; j != p_s_depth; ++j) {
  776. X          rp = &c_rt[p_stack[j]-1];
  777. X          switch (rp->RuleSelector) {
  778. X          case FTLOWPEERADDRESS:
  779. X             addrcpy(fp->Low.PeerAddress,
  780. X            rp->RuleMatchedValue, PEER_ADDR_LEN);
  781. X             addrcpy(fp->Low.PeerMask, rp->RuleMask, PEER_ADDR_LEN);
  782. X             break;
  783. X          case FTHIPEERADDRESS:
  784. X             addrcpy(fp->High.PeerAddress,
  785. X            rp->RuleMatchedValue, PEER_ADDR_LEN);
  786. X             addrcpy(fp->High.PeerMask, rp->RuleMask, PEER_ADDR_LEN);
  787. X             break;
  788. X          case FTLOWPEERTYPE:
  789. X          case FTHIPEERTYPE:
  790. X             fp->PeerAddrType = rp->RuleMatchedValue[0];
  791. X             fp->PeerTypeMask = rp->RuleMask[0];
  792. X             break;
  793. X          case FTLOWDETAILADDRESS:
  794. X             addrcpy(fp->Low.DetailAddress,
  795. X            rp->RuleMatchedValue, DETAIL_ADDR_LEN);
  796. X             addrcpy(fp->Low.DetailMask, rp->RuleMask, DETAIL_ADDR_LEN);
  797. X             break;
  798. X          case FTHIDETAILADDRESS:
  799. X             addrcpy(fp->High.DetailAddress,
  800. X            rp->RuleMatchedValue, DETAIL_ADDR_LEN);
  801. X             addrcpy(fp->High.DetailMask, rp->RuleMask, DETAIL_ADDR_LEN);
  802. X             break;
  803. X          case FTLOWDETAILTYPE:
  804. X          case FTHIDETAILTYPE:
  805. X             fp->DetailAddrType = rp->RuleMatchedValue[0];
  806. X             fp->DetailTypeMask = rp->RuleMask[0];
  807. X             break;
  808. X          case FTLOWADJACENTADDRESS:
  809. X             addrcpy(fp->Low.AdjAddress,
  810. X            rp->RuleMatchedValue, MAC_ADDR_LEN);
  811. X             addrcpy(fp->Low.AdjMask, rp->RuleMask, MAC_ADDR_LEN);
  812. X             break;
  813. X          case FTHIADJACENTADDRESS:
  814. X             addrcpy(fp->High.AdjAddress,
  815. X            rp->RuleMatchedValue, MAC_ADDR_LEN);
  816. X             addrcpy(fp->High.AdjMask, rp->RuleMask, MAC_ADDR_LEN);
  817. X             break;
  818. X             }
  819. X                  }
  820. X           init_flow(fp,FT_COUNT);
  821. X#ifdef GC_DEBUG
  822. X           dup_flow(fp, "adding count");
  823. X#endif
  824. X           if ((f = number_flow(fp)) == NULL) {
  825. X#ifdef GC_DEBUG
  826. X      printf("\nno room for count ..\n");
  827. X#endif
  828. X          free_flow(fp);  /* No room in flow_index */
  829. X          return 1;  /* Succeed: don't try to match again */
  830. X          }
  831. X           fp->link.count = rp;
  832. X           rp->RuleJumpIndex = f;
  833. X           }
  834. X        else fp = find_flow(j);
  835. X#ifdef COUNT_TRACE
  836. Xscpos(0,24);
  837. Xprintf("count ");  daddr(from->PeerAddress);
  838. Xprintf(" -> ");  daddr(to->PeerAddress);
  839. Xprintf("\n");
  840. X#endif
  841. X        break;  /* Count this PDU */
  842. X     case RA_TALLY:
  843. X        ap = &c_at[rp->RuleJumpIndex-1];
  844. X        if ((ht = ap->link.hash) == NULL) {  /* No hash table yet */
  845. X           ht = (struct hash_tbl far *)farmalloc(sizeof(struct hash_tbl));
  846. X           for (j = 0; j != HASHMOD; ++j) ht->hash_ent[j] = NULL;
  847. X           ap->link.hash = ht;
  848. X           ++n_hash_tables;  t_hash_size += HASHMOD;
  849. X           }
  850. X        if ((fp = search_hash_table(ht, from,to,pdu,
  851. X          ap, OK_to_add)) == NULL)
  852. X           return 2;  /* Not OK to add */
  853. X        break;  /* Count this PDU */
  854. X     case RA_AGGREGATE:
  855. X        ap = &c_at[rp->RuleJumpIndex-1];
  856. X        if ((fp = ap->link.action) == NULL) {
  857. X           if ((fp = get_flow()) == NULL)
  858. X          return 1;  /* Out of memory: don't try match again */
  859. X           bcopy((unsigned char far *)Key(ap),  /* bcopy (s,d,n) */
  860. X          (unsigned char far *)Key(fp), sizeof(struct flow_key));
  861. X               init_flow(fp,FT_AGGREGATE);
  862. X#ifdef GC_DEBUG
  863. X           dup_flow(fp, "adding aggregate");
  864. X#endif
  865. X           if (number_flow(fp) == NULL) {
  866. X#ifdef GC_DEBUG
  867. X      printf("\nno room for aggregate ..\n");
  868. X#endif
  869. X          free_flow(fp);  /* No room in flow_index */
  870. X          return 1;  /* Succeed: don't try to match again */
  871. X          }
  872. X           fp->link.action = ap;
  873. X           ap->link.action = fp;
  874. X           }
  875. X        break;  /* Count this PDU */
  876. X     case RA_SUCCEED:
  877. X        return 1;
  878. X     case RA_FAIL:
  879. X        return 0;
  880. X     case RA_PUSHTO:
  881. X        p_stack[p_s_depth++] = rx;  /* Remember which rules matched */
  882. X        rx = rp->RuleJumpIndex;
  883. X#ifdef STACK_CHECK
  884. X        if (p_s_depth >= RSTKSIZ) {
  885. X           scpos(0,24);
  886. X           printf("match oflo: depth=%d, stk=", p_s_depth);
  887. X           for (j = 0; j != p_s_depth; ++j) printf("%d,", p_stack[j]);
  888. X           printf("\n   LowPeer=");  daddr(from->PeerAddress);
  889. X           printf(", HighPeer=");  daddr(to->PeerAddress);
  890. X           printf("\n");
  891. X           return 0;
  892. X           }
  893. X#endif
  894. X        continue;
  895. X     case RA_POPTO:
  896. X        --p_s_depth;  /* Forget last matched rule */
  897. X        rx = rp->RuleJumpIndex;
  898. X#ifdef STACK_CHECK
  899. X        if (p_s_depth < 0) {
  900. X           scpos(0,24);
  901. X           printf("match uflo: stk=");
  902. X           for (j = 0; j != RSTKSIZ; ++j) printf("%d,", p_stack[j]);
  903. X           printf("\n   LowPeer=");  daddr(tally->Low.PeerAddress);
  904. X           printf(", HighPeer=");  daddr(tally->High.PeerAddress);
  905. X           printf("\n");
  906. X           return 0;
  907. X           }
  908. X#endif
  909. X        continue;
  910. X     case RA_GOTO:
  911. X        rx = rp->RuleJumpIndex;
  912. X#ifdef TESTING
  913. Xscpos(0,24);
  914. Xprintf("   GOTO %d\n", rx);
  915. X#endif
  916. X        continue;
  917. X        }
  918. X     if (forward) {
  919. X        fp->UpOctets += len;  fp->UpPDUs += 1;
  920. X        }
  921. X     else {
  922. X        fp->DownOctets += len;  fp->DownPDUs += 1;
  923. X        }
  924. X     fp->LastTime = s_uptime;
  925. X     return 1;
  926. X     }
  927. X      else ++rx;
  928. X      }
  929. X   return 0;  /* Not matched */
  930. X   }
  931. X
  932. X
  933. X#define MAXPKTLEN  1526
  934. X
  935. X#ifdef DECNET
  936. Xint dn_node(dn_addr)
  937. Xunsigned char far *dn_addr;
  938. X{
  939. X   return dn_addr[1]<<8 | dn_addr[0];
  940. X   }
  941. X
  942. X#define dn_area(node) (node >> 10)
  943. X#define dn_host(node) (node & 0x3FF)
  944. X#endif
  945. X
  946. Xvoid unpack_dn_node(ap, dn_addr)
  947. Xunsigned char far *ap;
  948. Xunsigned char far *dn_addr;
  949. X{
  950. X   unsigned char dl = dn_addr[1];
  951. X   ap[0] = dl >> 2;    /* DECnet area */
  952. X   ap[1] = dl & 0x03;  ap[2] = dn_addr[0];  /* DECnet host */
  953. X   ap[3] = 0;
  954. X   }
  955. X
  956. Xvoid unpack_at_node(ap, at_net,at_node)
  957. Xunsigned char far *ap;
  958. Xunsigned char far *at_net;
  959. Xunsigned char at_node;
  960. X{
  961. X   ap[0] = at_net[0];  ap[1] = at_net[1];
  962. X   ap[2] = at_node;
  963. X   ap[3] = 0;
  964. X   }
  965. X
  966. Xvoid pkt_monitor(unsigned char far *pp, int len, unsigned char type)
  967. X{
  968. X   unsigned char j, dtype, dx;
  969. X   union decnet far *dp;
  970. X   struct rule far *r;
  971. X#ifdef DECNET
  972. X   unsigned int dlen, snode, dnode, area, host;
  973. X#endif
  974. X
  975. X   addrcpy(data->Low.AdjAddress,&pp[6-SNAPFROM],MAC_ADDR_LEN);  /* Ethernet source */
  976. X   addrcpy(data->High.AdjAddress,&pp[0-SNAPFROM],MAC_ADDR_LEN);  /* Ethernet dest */
  977. X
  978. X   if (type == AT_IP) {
  979. X      data->PeerAddrType = AT_IP;
  980. X      addrcpy(data->Low.PeerAddress,&pp[26-SNAPFROM],PEER_ADDR_LEN);  /* IP source */
  981. X      addrcpy(data->High.PeerAddress,&pp[30-SNAPFROM],PEER_ADDR_LEN);  /* IP dest */
  982. X      j = data->DetailAddrType = pp[23-SNAPFROM];  /* IP Protocol Type */
  983. X      dx = 14 + ((pp[14-SNAPFROM] & 0x0F) << 2) - SNAPFROM;  /* HLEN */
  984. X     /* Data offset.  HLEN = IP header length in 32-bit units */
  985. X      if (j == PT_ICMP) {
  986. X     data->Low.DetailAddress[0] = data->High.DetailAddress[0] = 0;
  987. X     data->Low.DetailAddress[1] = pp[dx];  /* Type field */
  988. X     data->High.DetailAddress[1] = pp[dx+1];  /* Code field */
  989. X     }
  990. X      else {
  991. X     data->Low.DetailAddress[0] = pp[dx];  /* Source port */
  992. X     data->Low.DetailAddress[1] = pp[dx+1];
  993. X     data->High.DetailAddress[0] = pp[dx+2];  /* Dest port */
  994. X     data->High.DetailAddress[1] = pp[dx+3];
  995. X     }
  996. X      }
  997. X   else if (type == AT_NOVELL) {
  998. X      data->PeerAddrType = AT_NOVELL;
  999. X      addrcpy(data->Low.PeerAddress,&pp[20-SNAPFROM],PEER_ADDR_LEN);  /* IPX soure net */
  1000. X      addrcpy(data->High.PeerAddress,&pp[32-SNAPFROM],PEER_ADDR_LEN);  /* IPX dest net */
  1001. X      data->DetailAddrType = pp[19-SNAPFROM];  /* XNS packet type */
  1002. X      data->Low.DetailAddress[0] = pp[42-SNAPFROM];
  1003. X      data->Low.DetailAddress[1] = pp[43-SNAPFROM];  /* IPX source socket */
  1004. X      data->High.DetailAddress[0] = pp[30-SNAPFROM];
  1005. X      data->High.DetailAddress[1] = pp[31-SNAPFROM];  /* IPX dest socket */
  1006. X      }
  1007. X   else if (type == AT_ETHERTALK) {
  1008. X      data->PeerAddrType = AT_ETHERTALK;
  1009. X      unpack_at_node(data->Low.PeerAddress, &pp[28-SNAPFROM],pp[31-SNAPFROM]);  /* AT source */
  1010. X      unpack_at_node(data->High.PeerAddress, &pp[26-SNAPFROM],pp[30-SNAPFROM]);  /* AT source */
  1011. X      data->DetailAddrType = pp[34-SNAPFROM];  /* AT DDP protocol type */
  1012. X      data->Low.DetailAddress[0] = data->High.DetailAddress[0] = 0;
  1013. X      data->Low.DetailAddress[1] = pp[33-SNAPFROM];  /* AT source socket */
  1014. X      data->High.DetailAddress[1] = pp[32-SNAPFROM];  /* AT dest socket */
  1015. X      }
  1016. X   else if (type == AT_DECNET) {
  1017. X      data->PeerAddrType = AT_DECNET;
  1018. X      addrcpy(data->High.PeerAddress,null_flow->High.PeerAddress,PEER_ADDR_LEN);
  1019. X      dtype = pp[16-SNAPFROM];  /* DECnet packet type */
  1020. X      if (dtype != 0x81) dp = (union decnet far *)&pp[17-SNAPFROM];
  1021. X      else {
  1022. X     dtype = pp[17-SNAPFROM];
  1023. X     dp = (union decnet far *)&pp[18-SNAPFROM];
  1024. X     }
  1025. X      data->Low.DetailAddress[0] = data->High.DetailAddress[0] =
  1026. X     data->Low.DetailAddress[1] = data->High.DetailAddress[1] = 0;
  1027. X      switch (data->DetailAddrType = dtype & 0x0F) {
  1028. X      case 0x06:  /* Data */
  1029. X      case 0x0E:  /* Data + discard flag */
  1030. X     unpack_dn_node(data->Low.PeerAddress, dp->d.src_dn_addr);
  1031. X     unpack_dn_node(data->High.PeerAddress, dp->d.dest_dn_addr);
  1032. X#ifdef DECNET
  1033. X     dnode = dn_node(dp->d.dest_dn_addr);
  1034. X     snode = dn_node(dp->d.src_dn_addr);
  1035. X     fprintf(log,"Data to %d.%d from %d.%d\n",
  1036. X        dn_area(dnode),dn_host(dnode),
  1037. X        dn_area(snode),dn_host(snode) );
  1038. X#endif
  1039. X     break;
  1040. X      case 0x07:  /* Level 1 routing */
  1041. X     unpack_dn_node(data->Low.PeerAddress, dp->l1r.src_dn_addr);
  1042. X#ifdef DECNET
  1043. X     snode = dn_node(dp->l1r.src_dn_addr);
  1044. X     fprintf(log,"Level 1 routing from %d.%d\n",
  1045. X        dn_area(snode),dn_host(snode));
  1046. X#endif
  1047. X     break;
  1048. X      case 0x09:  /* Level 2 routing */
  1049. X     unpack_dn_node(data->Low.PeerAddress, dp->l2r.src_dn_addr);
  1050. X#ifdef DECNET
  1051. X     snode = dn_node(dp->l2r.src_dn_addr);
  1052. X     fprintf(log,"Level 2 routing from %d.%d\n",
  1053. X        dn_area(snode),dn_host(snode));
  1054. X#endif
  1055. X     break;
  1056. X      case 0x0B:  /* Router hello */
  1057. X     unpack_dn_node(data->Low.PeerAddress, dp->rh.src_dn_addr);
  1058. X#ifdef DECNET
  1059. X     snode = dn_node(dp->rh.src_dn_addr);
  1060. X     dnode = dn_node(dp->rh.rtr_dn_addr);
  1061. X     fprintf(log,"Router hello from %d.%d, other router %d.%d\n",
  1062. X        dn_area(snode),dn_host(snode),
  1063. X        dn_area(dnode),dn_host(dnode) );
  1064. X#endif
  1065. X     break;
  1066. X      case 0x0D:  /* Endnode hello */
  1067. X     unpack_dn_node(data->Low.PeerAddress, dp->eh.src_dn_addr);
  1068. X#ifdef DECNET
  1069. X     snode = dn_node(dp->eh.src_dn_addr);
  1070. X     dnode = dn_node(dp->eh.rtr_dn_addr);
  1071. X     fprintf(log,"Endnode hello from %d.%d, designated router %d.%d\n",
  1072. X        dn_area(snode),dn_host(snode),
  1073. X        dn_area(dnode),dn_host(dnode) );
  1074. X#endif
  1075. X     break;
  1076. X      default:  /* Unknown DECnet type */
  1077. X     scpos(0,24);
  1078. X     printf("\nDN pkt type %02x: ", dtype);
  1079. X     for (j=0; j != 16; ++j) printf(" %02x",pp[j-SNAPFROM]);
  1080. X     printf("\n");
  1081. X     for (j=16; j != 34; ++j) printf(" %02x",pp[j-SNAPFROM]);
  1082. X     printf("\n");
  1083. X#ifdef TESTING
  1084. X     if (!log) open_log();
  1085. X     fprintf(log, "\nDN pkt type %02x: ", dtype);
  1086. X     for (j=17; j != 34; ++j) fprintf(log," %02x",pp[j-SNAPFROM]);
  1087. X     fprintf(log, "\n");
  1088. X#endif
  1089. X     return;  /* Ignore it */
  1090. X     }
  1091. X      }
  1092. X   else if (type == AT_DUMMY) {
  1093. X      if (++dummypackets == 1000) {
  1094. X     ++kilodummypackets;  dummypackets = 0;
  1095. X     }
  1096. X      ++dummypacketrate;
  1097. X      return;  /* Don't try to match the dummy packets! */
  1098. X      }
  1099. X
  1100. X#ifdef TESTING
  1101. X   j = pkt_match(1,0, len, data, &data->Low, &data->High);
  1102. Xfprintf(log,"pkt_match(1,0) returned %d\n", j);
  1103. Xswitch (j) {
  1104. X#else
  1105. X   switch (pkt_match(1,0, len, data, &data->Low, &data->High)) {
  1106. X#endif
  1107. X   case 0:  /* Failed */
  1108. X      pkt_match(0,1, len, data, &data->High, &data->Low);
  1109. X      return;
  1110. X   case 1:  /* Matched */
  1111. X      return;
  1112. X   case 2:  /* Matched but not yet in tally  */
  1113. X      if (pkt_match(0,1, len, data, &data->High, &data->Low) == 1)
  1114. X     return;  /* Matched */
  1115. X      pkt_match(1,1, len, data, &data->Low, &data->High);
  1116. X      return;
  1117. X      }
  1118. X   }
  1119. X
  1120. X#ifdef AU_MSDOS
  1121. Xvoid save_time()
  1122. X{
  1123. X   s_tod_h = tod_h;  s_tod_m = tod_m;  s_tod_s = tod_s;
  1124. X   elapsed_sec = 0;
  1125. X   }
  1126. X#endif
  1127. X
  1128. X#ifdef DEBUG
  1129. Xvoid write_flows()
  1130. X{
  1131. X   int x;
  1132. X   char msg[40];
  1133. X   struct flow far *t;
  1134. X   if (!log) open_log();
  1135. X   for (x = 1; x <= nflows; ++x) {
  1136. X      if ((t = find_flow(x)) == NULL) continue;
  1137. X      sprintf(msg,"flow %d:  ",x);  pkey(msg,t);
  1138. X      fprintf(log,"   Up: %8lu %6lu Down: %8lu %6lu Time: %8lu %8lu\n",
  1139. X     t->UpOctets,t->UpPDUs, t->DownOctets,t->DownPDUs,
  1140. X     t->FirstTime, t->LastTime);
  1141. X      }
  1142. X   fclose(log);  log = NULL;
  1143. X   }
  1144. X#endif
  1145. X
  1146. Xvoid zero_stats(void)
  1147. X{
  1148. X   FlowsRecovered = n_matches = n_hash_compares = n_hash_searches = 0L;
  1149. X   clear_pkt_stats = 1;
  1150. X   display_msg(1,"Statistics Zeroed");
  1151. X   }
  1152. X
  1153. Xvoid show_stats(void)
  1154. X{
  1155. X   unsigned int i,j;
  1156. X   unsigned long aps,apb, kdp;
  1157. X   char msg[60];
  1158. X#ifdef AU_MSDOS
  1159. X   if (stats_time == 0 || npackets == 0 ||
  1160. X     kilodummypackets == 0 || mindummyrate == 0)
  1161. X#else
  1162. X   if (stats_time == 0 || npackets == 0)
  1163. X#endif
  1164. X      return;  /* Avoid divides by zero */
  1165. X
  1166. X   display_msg(1,"Meter Statistics ..");
  1167. X   aps = (npackets*10+5L)/(stats_time*10L);
  1168. X#ifdef AU_MSDOS
  1169. X   apb = (t_backlog*10+5L)/(stats_time*10L);
  1170. X   sprintf(msg,"Av pkt/s %lu, av pkt backlog %lu", aps,apb);
  1171. X   display_msg(0,msg);
  1172. X   sprintf(msg,"Max pkt/s %u, max pkt backlog %u",
  1173. X      max_pkt_rate,max_pkt_backlog);
  1174. X   display_msg(0,msg);
  1175. X#else
  1176. X   sprintf(msg,"Av pkt/s %lu, max pkt/s %u", aps,max_pkt_rate);
  1177. X   display_msg(0,msg);
  1178. X#endif
  1179. X   if (kilodummypackets != 0) {
  1180. X      if (dummypackets >= 500) ++kilodummypackets;
  1181. X      i = kilodummypackets*1000L/(kilodummypackets+npackets/1000L);
  1182. X      j = (mindummyrate*10000L+5L)/((mindummyrate+mdpacketrate)*10L);
  1183. X      sprintf(msg,"Idle time av %u.%u, min %u.%u %", i/10,i%10, j/10,j%10);
  1184. X      display_msg(0,msg);
  1185. X      }
  1186. X   sprintf(msg,"%u flows in use (max %u)",nflows,mxflowsp1-1);
  1187. X   display_msg(0,msg);
  1188. X   sprintf(msg,"%lu flows recovered (GC: %u  %u %u)",
  1189. X      FlowsRecovered, gc_interval,gc_f,gc_e);
  1190. X   display_msg(0,msg);
  1191. X   i = (n_matches*100L+5L)/(npackets*10L);
  1192. X   j = (n_hash_searches*100L+5L)/(npackets*10L);
  1193. X   sprintf(msg,"%u.%u rules/pkt, %u.%u tallies/pkt",
  1194. X      i/10,i%10, j/10,j%10);
  1195. X   display_msg(0,msg);
  1196. X   if (n_hash_searches != 0) {
  1197. X      i = (n_hash_compares*100L+5L)/(n_hash_searches*10L);
  1198. X      sprintf(msg,"%u.%u compares/tally", i/10,i%10);
  1199. X      display_msg(0,msg);
  1200. X      sprintf(msg,"%u hash slots, %u in use, ", t_hash_size,n_hash_ents);
  1201. X      }
  1202. X   }
  1203. X
  1204. Xvoid init_monitor()
  1205. X{
  1206. X   int j;
  1207. X   unsigned char far *fp;
  1208. X   unsigned char *np;
  1209. X#ifdef AU_MSDOS
  1210. X   set_tod();
  1211. X   save_time();  /* For screen display */
  1212. X   start_uptime_clock();  /* Starts 1 tick early; flows have CreateTime > 1 */
  1213. X#else
  1214. X   boot_time = 0;
  1215. X#endif
  1216. X   data = get_flow();  null_flow = get_flow();  tally = get_flow();
  1217. X   fp = (unsigned char far *)null_flow;
  1218. X   for (j = 0; j != sizeof(struct flow); ++j) *fp++ = 0;
  1219. X   rule_hash = (int far *)farmalloc(sizeof(int)*(rh_size = INITHSZ));
  1220. X   flow_ix = (struct flow far **)malloc(sizeof(struct flow far *)*(mxflowsp1));
  1221. X   for (j = 0; j != mxflowsp1; ++j) flow_ix[j] = NULL;
  1222. X   nflows = 0;  /* No accounting flows in use yet */
  1223. X   gcf_ix = empty_ix = mxflowsp1;  /* Flow 2 will be the first allocated */
  1224. X   np = (unsigned char *)CTi;
  1225. X   for (j = 0; j != sizeof(CTi); ++j) *np++ = 0;
  1226. X   n_collectors = 0;
  1227. X   s_uptime = uptime();
  1228. X
  1229. X   /* Start with default rule and action tables */
  1230. X
  1231. X   rule_table[0] = (struct rule far *)default_rule_table;
  1232. X   rt_size[0] = DRT_SIZE;
  1233. X   action_table[0] = (struct flow far *)default_action_table;
  1234. X   at_size[0] = DAT_SIZE;
  1235. X   for (j = 1; j != MXNRTBLS; ++j) {
  1236. X      rule_table[j] = NULL;  action_table[j] = NULL;
  1237. X      rt_size[j] = at_size[j] = 0;
  1238. X      }
  1239. X   open_rule_set(1, 1); /* Open set 1 */
  1240. X   }
  1241. X
  1242. Xvoid show_help()
  1243. X{
  1244. X   display_msg(0,"Copyright (C) 1992,1993 by Nevil Brownlee");
  1245. X   display_msg(0,"Computer Centre, University of Auckland");
  1246. X   display_msg(0,"");
  1247. X   display_msg(0,"Keyboard commands ..");
  1248. X   display_msg(0,"");
  1249. X#ifdef AU_MSDOS
  1250. X   display_msg(0,"  b: show Bad packet counts");
  1251. X   display_msg(0,"  m: show Memory usage");
  1252. X#endif
  1253. X   display_msg(0,"  s: show Statistics");
  1254. X   display_msg(0,"  v: show meter Version");
  1255. X   display_msg(0,"  z: Zero statistics");
  1256. X   if (kb_enabled) {
  1257. X      display_msg(0,"");
  1258. X      display_msg(0,"Esc: stop metering, exit NeTraMet");
  1259. X      }
  1260. X   }
  1261. X
  1262. Xvoid handle_kb(ch)
  1263. Xint ch;
  1264. X{
  1265. X   switch (tolower(ch)) {
  1266. X   case 's':
  1267. X      show_stats();
  1268. X      break;
  1269. X   case 't':
  1270. X      show_meter_time();
  1271. X      break;
  1272. X#ifdef DEBUG
  1273. X   case 'x':
  1274. X      if (kb_enabled) write_flows();
  1275. X      break;
  1276. X#endif
  1277. X   case 'z':
  1278. X      zero_stats();
  1279. X      break;
  1280. X   case '?':
  1281. X      show_help();
  1282. X      break;
  1283. X   default:
  1284. X      break;
  1285. X      }
  1286. X   }
  1287. END_OF_FILE
  1288.   if test 38647 -ne `wc -c <'netramet/src/meter/flowhash.c'`; then
  1289.     echo shar: \"'netramet/src/meter/flowhash.c'\" unpacked with wrong size!
  1290.   fi
  1291.   # end of 'netramet/src/meter/flowhash.c'
  1292. fi
  1293. if test -f 'netramet/src/snmplib/parse.c' -a "${1}" != "-c" ; then 
  1294.   echo shar: Will not clobber existing file \"'netramet/src/snmplib/parse.c'\"
  1295. else
  1296.   echo shar: Extracting \"'netramet/src/snmplib/parse.c'\" \(22322 characters\)
  1297.   sed "s/^X//" >'netramet/src/snmplib/parse.c' <<'END_OF_FILE'
  1298. X/***********************************************************
  1299. X    Copyright 1989 by Carnegie Mellon University
  1300. X
  1301. X                      All Rights Reserved
  1302. X
  1303. XPermission to use, copy, modify, and distribute this software and its 
  1304. Xdocumentation for any purpose and without fee is hereby granted, 
  1305. Xprovided that the above copyright notice appear in all copies and that
  1306. Xboth that copyright notice and this permission notice appear in 
  1307. Xsupporting documentation, and that the name of CMU not be
  1308. Xused in advertising or publicity pertaining to distribution of the
  1309. Xsoftware without specific, written prior permission.  
  1310. X
  1311. XCMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  1312. XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  1313. XCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  1314. XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  1315. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  1316. XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  1317. XSOFTWARE.
  1318. X******************************************************************/
  1319. X/*
  1320. X * parse.c
  1321. X */
  1322. X#include <stdio.h>
  1323. X#include <ctype.h>
  1324. X#include <sys/types.h>
  1325. X#include "parse.h"
  1326. X
  1327. X/*
  1328. X * This is one element of an object identifier with either an integer subidentifier,
  1329. X * or a textual string label, or both.
  1330. X * The subid is -1 if not present, and label is NULL if not present.
  1331. X */
  1332. Xstruct subid {
  1333. X    int subid;
  1334. X    char *label;
  1335. X};
  1336. X
  1337. Xint Line = 1;
  1338. X
  1339. X/* types of tokens */
  1340. X#define    CONTINUE    -1
  1341. X#define LABEL        1
  1342. X#define SUBTREE        2
  1343. X#define SYNTAX        3
  1344. X#define OBJID        4
  1345. X#define OCTETSTR    5
  1346. X#define INTEGER        6
  1347. X#define NETADDR        7
  1348. X#define    IPADDR        8
  1349. X#define COUNTER        9
  1350. X#define GAUGE        10
  1351. X#define TIMETICKS   11
  1352. X#define OPAQUE        12
  1353. X#define NUL        13
  1354. X#define SEQUENCE    14
  1355. X#define OF        15    /* SEQUENCE OF */
  1356. X#define OBJTYPE        16
  1357. X#define ACCESS        17
  1358. X#define READONLY    18
  1359. X#define READWRITE   19
  1360. X#define    WRITEONLY   20
  1361. X#define NOACCESS    21
  1362. X#define STATUS        22
  1363. X#define MANDATORY   23
  1364. X#define OPTIONAL    24
  1365. X#define OBSOLETE    25
  1366. X#define RECOMMENDED 26
  1367. X#define PUNCT        27
  1368. X#define EQUALS        28
  1369. X
  1370. Xstruct tok {
  1371. X    char *name;            /* token name */
  1372. X    int len;            /* length not counting nul */
  1373. X    int token;            /* value */
  1374. X    int hash;            /* hash of name */
  1375. X    struct tok *next;        /* pointer to next in hash table */
  1376. X};
  1377. X
  1378. X
  1379. Xstruct tok tokens[] = {
  1380. X    { "obsolete", sizeof ("obsolete")-1, OBSOLETE },
  1381. X    { "Opaque", sizeof ("Opaque")-1, OPAQUE },
  1382. X    { "recommended", sizeof("recommended")-1, RECOMMENDED }, 
  1383. X    { "optional", sizeof ("optional")-1, OPTIONAL },
  1384. X    { "mandatory", sizeof ("mandatory")-1, MANDATORY },
  1385. X    { "not-accessible", sizeof ("not-accessible")-1, NOACCESS },
  1386. X    { "write-only", sizeof ("write-only")-1, WRITEONLY },
  1387. X    { "read-write", sizeof ("read-write")-1, READWRITE },
  1388. X    { "TimeTicks", sizeof ("TimeTicks")-1, TIMETICKS },
  1389. X    { "OBJECTIDENTIFIER", sizeof ("OBJECTIDENTIFIER")-1, OBJID },
  1390. X    /*
  1391. X     * This CONTINUE appends the next word onto OBJECT,
  1392. X     * hopefully matching OBJECTIDENTIFIER above.
  1393. X     */
  1394. X    { "OBJECT", sizeof ("OBJECT")-1, CONTINUE },
  1395. X    { "NetworkAddress", sizeof ("NetworkAddress")-1, NETADDR },
  1396. X    { "Gauge", sizeof ("Gauge")-1, GAUGE },
  1397. X    { "OCTETSTRING", sizeof ("OCTETSTRING")-1, OCTETSTR },
  1398. X    { "OCTET", sizeof ("OCTET")-1, -1 },
  1399. X    { "OF", sizeof ("OF")-1, OF },
  1400. X    { "SEQUENCE", sizeof ("SEQUENCE")-1, SEQUENCE },
  1401. X    { "NULL", sizeof ("NULL")-1, NUL },
  1402. X    { "IpAddress", sizeof ("IpAddress")-1, IPADDR },
  1403. X    { "INTEGER", sizeof ("INTEGER")-1, INTEGER },
  1404. X    { "Counter", sizeof ("Counter")-1, COUNTER },
  1405. X    { "read-only", sizeof ("read-only")-1, READONLY },
  1406. X    { "ACCESS", sizeof ("ACCESS")-1, ACCESS },
  1407. X    { "STATUS", sizeof ("STATUS")-1, STATUS },
  1408. X    { "SYNTAX", sizeof ("SYNTAX")-1, SYNTAX },
  1409. X    { "OBJECT-TYPE", sizeof ("OBJECT-TYPE")-1, OBJTYPE },
  1410. X    { "{", sizeof ("{")-1, PUNCT },
  1411. X    { "}", sizeof ("}")-1, PUNCT },
  1412. X    { "::=", sizeof ("::=")-1, EQUALS },
  1413. X    { NULL }
  1414. X};
  1415. X
  1416. X#define    HASHSIZE    32
  1417. X#define    BUCKET(x)    (x & 0x01F)
  1418. X
  1419. Xstruct tok    *buckets[HASHSIZE];
  1420. X
  1421. Xstatic
  1422. Xhash_init()
  1423. X{
  1424. X    register struct tok    *tp;
  1425. X    register char    *cp;
  1426. X    register int    h;
  1427. X    register int    b;
  1428. X
  1429. X    for (tp = tokens; tp->name; tp++) {
  1430. X        for (h = 0, cp = tp->name; *cp; cp++)
  1431. X            h += *cp;
  1432. X        tp->hash = h;
  1433. X        b = BUCKET(h);
  1434. X        if (buckets[b])
  1435. X            tp->next = buckets[b];
  1436. X        buckets[b] = tp;
  1437. X    }
  1438. X}
  1439. X
  1440. X
  1441. Xstatic char *
  1442. XMalloc(num)
  1443. X    unsigned num;
  1444. X{
  1445. X    char *cp;
  1446. X    char *malloc();
  1447. X    
  1448. X    /* this is to fix (what seems to be) a problem with the IBM RT C library malloc */
  1449. X    if (num < 16)
  1450. X    num = 16;
  1451. X    cp = malloc(num);
  1452. X    return cp;
  1453. X}
  1454. X
  1455. Xstatic
  1456. Xprint_error(string, token)
  1457. X    char *string;
  1458. X    char *token;
  1459. X{
  1460. X    if (token)
  1461. X    fprintf(stderr, "%s(%s): On or around line %d\n", string, token, Line);
  1462. X    else
  1463. X    fprintf(stderr, "%s: On or around line %d\n", string, Line);
  1464. X}
  1465. X
  1466. X#ifdef TEST
  1467. Xprint_subtree(tree, count)
  1468. X    struct tree *tree;
  1469. X    int count;
  1470. X{
  1471. X    struct tree *tp;
  1472. X    int i;
  1473. X
  1474. X    for(i = 0; i < count; i++)
  1475. X    printf("  ");
  1476. X    printf("Children of %s:\n", tree->label);
  1477. X    count++;
  1478. X    for(tp = tree->child_list; tp; tp = tp->next_peer){
  1479. X    for(i = 0; i < count; i++)
  1480. X        printf("  ");
  1481. X    printf("%s\n", tp->label);
  1482. X    }
  1483. X    for(tp = tree->child_list; tp; tp = tp->next_peer){
  1484. X    print_subtree(tp, count);
  1485. X    }
  1486. X}
  1487. X#endif /* TEST */
  1488. X
  1489. X
  1490. Xstatic struct tree *
  1491. Xbuild_tree(nodes)
  1492. X    struct node *nodes;
  1493. X{
  1494. X    struct node *np;
  1495. X    struct tree *tp;
  1496. X    
  1497. X    /* build root node */
  1498. X    tp = (struct tree *)Malloc(sizeof(struct tree));
  1499. X    tp->parent = NULL;
  1500. X    tp->next_peer = NULL;
  1501. X    tp->child_list = NULL;
  1502. X    tp->enums = NULL;
  1503. X    strcpy(tp->label, "iso");
  1504. X    tp->subid = 1;
  1505. X    tp->type = 0;
  1506. X    /* grow tree from this root node */
  1507. X    do_subtree(tp, &nodes);
  1508. X#ifdef TEST
  1509. X    print_subtree(tp, 0);
  1510. X#endif /* TEST */
  1511. X    /* If any nodes are left, the tree is probably inconsistent */
  1512. X    if (nodes){
  1513. X    fprintf(stderr, "The mib description doesn't seem to be consistent.\n");
  1514. X    fprintf(stderr, "Some nodes couldn't be linked under the \"iso\" tree.\n");
  1515. X    fprintf(stderr, "these nodes are left:\n");
  1516. X    for(np = nodes; np; np = np->next)
  1517. X        fprintf(stderr, "%s ::= { %s %d } (%d)\n", np->label, np->parent, np->subid,
  1518. X            np->type);
  1519. X    }
  1520. X    return tp;
  1521. X}
  1522. X
  1523. X
  1524. X/*
  1525. X * Find all the children of root in the list of nodes.  Link them into the
  1526. X * tree and out of the nodes list.
  1527. X */
  1528. Xstatic
  1529. Xdo_subtree(root, nodes)
  1530. X    struct tree *root;
  1531. X    struct node **nodes;
  1532. X{
  1533. X    register struct tree *tp;
  1534. X    struct tree *peer = NULL;
  1535. X    register struct node *np;
  1536. X    struct node *oldnp = NULL, *child_list = NULL, *childp = NULL;
  1537. X    
  1538. X    tp = root;
  1539. X    /*
  1540. X     * Search each of the nodes for one whose parent is root, and
  1541. X     * move each into a separate list.
  1542. X     */
  1543. X    for(np = *nodes; np; np = np->next){
  1544. X    if ((tp->label[0] == np->parent[0]) && !strcmp(tp->label, np->parent)){
  1545. X        if (child_list == NULL){
  1546. X        child_list = childp = np;   /* first entry in child list */
  1547. X        } else {
  1548. X        childp->next = np;
  1549. X        childp = np;
  1550. X        }
  1551. X        /* take this node out of the node list */
  1552. X        if (oldnp == NULL){
  1553. X        *nodes = np->next;  /* fix root of node list */
  1554. X        } else {
  1555. X        oldnp->next = np->next;    /* link around this node */
  1556. X        }
  1557. X    } else {
  1558. X        oldnp = np;
  1559. X    }
  1560. X    }
  1561. X    if (childp)
  1562. X    childp->next = 0;    /* re-terminate list */
  1563. X    /*
  1564. X     * Take each element in the child list and place it into the tree.
  1565. X     */
  1566. X    for(np = child_list; np; np = np->next){
  1567. X    tp = (struct tree *)Malloc(sizeof(struct tree));
  1568. X    tp->parent = root;
  1569. X    tp->next_peer = NULL;
  1570. X    tp->child_list = NULL;
  1571. X    strcpy(tp->label, np->label);
  1572. X    tp->subid = np->subid;
  1573. X    switch(np->type){
  1574. X        case OBJID:
  1575. X        tp->type = TYPE_OBJID;
  1576. X        break;
  1577. X        case OCTETSTR:
  1578. X        tp->type = TYPE_OCTETSTR;
  1579. X        break;
  1580. X        case INTEGER:
  1581. X        tp->type = TYPE_INTEGER;
  1582. X        break;
  1583. X        case NETADDR:
  1584. X        tp->type = TYPE_IPADDR;
  1585. X        break;
  1586. X        case IPADDR:
  1587. X        tp->type = TYPE_IPADDR;
  1588. X        break;
  1589. X        case COUNTER:
  1590. X        tp->type = TYPE_COUNTER;
  1591. X        break;
  1592. X        case GAUGE:
  1593. X        tp->type = TYPE_GAUGE;
  1594. X        break;
  1595. X        case TIMETICKS:
  1596. X        tp->type = TYPE_TIMETICKS;
  1597. X        break;
  1598. X        case OPAQUE:
  1599. X        tp->type = TYPE_OPAQUE;
  1600. X        break;
  1601. X        case NUL:
  1602. X        tp->type = TYPE_NULL;
  1603. X        break;
  1604. X        default:
  1605. X        tp->type = TYPE_OTHER;
  1606. X        break;
  1607. X    }
  1608. X    tp->enums = np->enums;
  1609. X    np->enums = NULL;    /* so we don't free them later */
  1610. X    if (root->child_list == NULL){
  1611. X        root->child_list = tp;
  1612. X    } else {
  1613. X        peer->next_peer = tp;
  1614. X    }
  1615. X    peer = tp;
  1616. X    do_subtree(tp, nodes);    /* recurse on this child */
  1617. X    }
  1618. X    /* free all nodes that were copied into tree */
  1619. X    for(np = child_list; np;){
  1620. X    oldnp = np;
  1621. X    np = np->next;
  1622. X    free_node(oldnp);
  1623. X    }
  1624. X}
  1625. X
  1626. X
  1627. X/*
  1628. X * Takes a list of the form:
  1629. X * { iso org(3) dod(6) 1 }
  1630. X * and creates several nodes, one for each parent-child pair.
  1631. X * Returns NULL on error.
  1632. X */
  1633. Xstatic int
  1634. Xgetoid(fp, oid,  length)
  1635. X    register FILE *fp;
  1636. X    register struct subid *oid;    /* an array of subids */
  1637. X    int length;        /* the length of the array */
  1638. X{
  1639. X    register int count;
  1640. X    int type;
  1641. X    char token[64], label[32];
  1642. X    register char *cp, *tp;
  1643. X
  1644. X    if ((type = get_token(fp, token)) != PUNCT){
  1645. X    if (type == -1)
  1646. X        print_error("Unexpected EOF", (char *)NULL);
  1647. X    else
  1648. X        print_error("Unexpected", token);
  1649. X    return NULL;
  1650. X    }
  1651. X    if (*token != '{'){
  1652. X    print_error("Unexpected", token);
  1653. X    return NULL;
  1654. X    }
  1655. X    for(count = 0; count < length; count++, oid++){
  1656. X    oid->label = 0;
  1657. X    oid->subid = -1;
  1658. X    if ((type = get_token(fp, token)) != LABEL){
  1659. X        if (type == -1){
  1660. X        print_error("Unexpected EOF", (char *)NULL);
  1661. X        return NULL;
  1662. X        }
  1663. X        else if (type == PUNCT && *token == '}'){
  1664. X        return count;
  1665. X        } else {
  1666. X        print_error("Unexpected", token);
  1667. X        return NULL;
  1668. X        }
  1669. X    }
  1670. X    tp = token;
  1671. X    if (!isdigit(*tp)){
  1672. X        /* this entry has a label */
  1673. X        cp = label;
  1674. X        while(*tp && *tp != '(')
  1675. X        *cp++ = *tp++;
  1676. X        *cp = 0;
  1677. X        cp = (char *)Malloc((unsigned)strlen(label));
  1678. X        strcpy(cp, label);
  1679. X        oid->label = cp;
  1680. X        if (*tp == '('){
  1681. X        /* this entry has a label-integer pair in the form label(integer). */
  1682. X        cp = ++tp;
  1683. X        while(*cp && *cp != ')')
  1684. X            cp++;
  1685. X        if (*cp == ')')
  1686. X            *cp = 0;
  1687. X        else {
  1688. X            print_error("No terminating parenthesis", (char *)NULL);
  1689. X            return NULL;
  1690. X        }
  1691. X        oid->subid = atoi(tp);
  1692. X        }
  1693. X    } else {
  1694. X        /* this entry  has just an integer sub-identifier */
  1695. X        oid->subid = atoi(tp);
  1696. X    }
  1697. X    }
  1698. X    return count;
  1699. X
  1700. X
  1701. X}
  1702. X
  1703. Xstatic
  1704. Xfree_node(np)
  1705. X    struct node *np;
  1706. X{
  1707. X    struct enum_list *ep, *tep;
  1708. X
  1709. X    ep = np->enums;
  1710. X    while(ep){
  1711. X    tep = ep;
  1712. X    ep = ep->next;
  1713. X    free((char *)tep);
  1714. X    }
  1715. X    free((char *)np);
  1716. X}
  1717. X
  1718. X/*
  1719. X * Parse an entry of the form:
  1720. X * label OBJECT IDENTIFIER ::= { parent 2 }
  1721. X * The "label OBJECT IDENTIFIER" portion has already been parsed.
  1722. X * Returns 0 on error.
  1723. X */
  1724. Xstatic struct node *
  1725. Xparse_objectid(fp, name)
  1726. X    FILE *fp;
  1727. X    char *name;
  1728. X{
  1729. X    int type;
  1730. X    char token[64];
  1731. X    register int count;
  1732. X    register struct subid *op, *nop;
  1733. X    int length;
  1734. X    struct subid oid[16];
  1735. X    struct node *np, *root, *oldnp = NULL;
  1736. X
  1737. X    type = get_token(fp, token);
  1738. X    if (type != EQUALS){
  1739. X    print_error("Bad format", token);
  1740. X    return 0;
  1741. X    }
  1742. X    if (length = getoid(fp, oid, 16)){
  1743. X    np = root = (struct node *)Malloc(sizeof(struct node));
  1744. X    /*
  1745. X     * For each parent-child subid pair in the subid array,
  1746. X     * create a node and link it into the node list.
  1747. X     */
  1748. X    for(count = 0, op = oid, nop=oid+1; count < (length - 2); count++,
  1749. X        op++, nop++){
  1750. X        /* every node must have parent's name and child's name or number */
  1751. X        if (op->label && (nop->label || (nop->subid != -1))){
  1752. X        strcpy(np->parent, op->label);
  1753. X        if (nop->label)
  1754. X            strcpy(np->label, nop->label);
  1755. X        if (nop->subid != -1)
  1756. X            np->subid = nop->subid;
  1757. X        np ->type = 0;
  1758. X        np->enums = 0;
  1759. X        /* set up next entry */
  1760. X        np->next = (struct node *)Malloc(sizeof(*np->next));
  1761. X        oldnp = np;
  1762. X        np = np->next;
  1763. X        }
  1764. X    }
  1765. X    np->next = (struct node *)NULL;
  1766. X    /*
  1767. X     * The above loop took care of all but the last pair.  This pair is taken
  1768. X     * care of here.  The name for this node is taken from the label for this
  1769. X     * entry.
  1770. X     * np still points to an unused entry.
  1771. X     */
  1772. X    if (count == (length - 2)){
  1773. X        if (op->label){
  1774. X        strcpy(np->parent, op->label);
  1775. X        strcpy(np->label, name);
  1776. X        if (nop->subid != -1)
  1777. X            np->subid = nop->subid;
  1778. X        else
  1779. X            print_error("Warning: This entry is pretty silly", token);
  1780. X        } else {
  1781. X        free_node(np);
  1782. X        if (oldnp)
  1783. X            oldnp->next = NULL;
  1784. X        else
  1785. X            return NULL;
  1786. X        }
  1787. X    } else {
  1788. X        print_error("Missing end of oid", (char *)NULL);
  1789. X        free_node(np);   /* the last node allocated wasn't used */
  1790. X        if (oldnp)
  1791. X        oldnp->next = NULL;
  1792. X        return NULL;
  1793. X    }
  1794. X    /* free the oid array */
  1795. X    for(count = 0, op = oid; count < length; count++, op++){
  1796. X        if (op->label)
  1797. X        free(oid->label);
  1798. X        op->label = 0;
  1799. X    }
  1800. X    return root;
  1801. X    } else {
  1802. X    print_error("Bad object identifier", (char *)NULL);
  1803. X    return 0;
  1804. X    }
  1805. X}
  1806. X
  1807. X/*
  1808. X * Parses an asn type.  This structure is ignored by this parser.
  1809. X * Returns NULL on error.
  1810. X */
  1811. Xstatic int
  1812. Xparse_asntype(fp)
  1813. X    FILE *fp;
  1814. X{
  1815. X    int type;
  1816. X    char token[64];
  1817. X
  1818. X    type = get_token(fp, token);
  1819. X    if (type != SEQUENCE){
  1820. X    print_error("Not a sequence", (char *)NULL); /* should we handle this */
  1821. X    return NULL;
  1822. X    }
  1823. X    while((type = get_token(fp, token)) != NULL){
  1824. X    if (type == -1)
  1825. X        return NULL;
  1826. X    if (type == PUNCT && (token[0] == '}' && token[1] == '\0'))
  1827. X        return -1;
  1828. X    }
  1829. X    print_error("Premature end of file", (char *)NULL);
  1830. X    return NULL;
  1831. X}
  1832. X
  1833. X/*
  1834. X * Parses an OBJECT TYPE macro.
  1835. X * Returns 0 on error.
  1836. X */
  1837. Xstatic struct node *
  1838. Xparse_objecttype(fp, name)
  1839. X    register FILE *fp;
  1840. X    char *name;
  1841. X{
  1842. X    register int type;
  1843. X    char token[64];
  1844. X    int count, length;
  1845. X    struct subid oid[16];
  1846. X    char syntax[32];
  1847. X    int nexttype;
  1848. X    char nexttoken[64];
  1849. X    register struct node *np;
  1850. X    register struct enum_list *ep;
  1851. X    register char *cp;
  1852. X    register char *tp;
  1853. X
  1854. X    type = get_token(fp, token);
  1855. X    if (type != SYNTAX){
  1856. X    print_error("Bad format for OBJECT TYPE", token);
  1857. X    return 0;
  1858. X    }
  1859. X    np = (struct node *)Malloc(sizeof(struct node));
  1860. X    np->next = 0;
  1861. X    np->enums = 0;
  1862. X    type = get_token(fp, token);
  1863. X    nexttype = get_token(fp, nexttoken);
  1864. X    np->type = type;
  1865. X    switch(type){
  1866. X    case SEQUENCE:
  1867. X        strcpy(syntax, token);
  1868. X        if (nexttype == OF){
  1869. X        strcat(syntax, " ");
  1870. X        strcat(syntax, nexttoken);
  1871. X        nexttype = get_token(fp, nexttoken);
  1872. X        strcat(syntax, " ");
  1873. X        strcat(syntax, nexttoken);
  1874. X        nexttype = get_token(fp, nexttoken);
  1875. X        }
  1876. X        break;
  1877. X    case INTEGER:
  1878. X        strcpy(syntax, token);
  1879. X        if (nexttype == PUNCT &&
  1880. X        (nexttoken[0] == '{' && nexttoken[1] == '\0')) {
  1881. X        /* if there is an enumeration list, parse it */
  1882. X        while((type = get_token(fp, token)) != NULL){
  1883. X            if (type == -1){
  1884. X            free_node(np);
  1885. X            return 0;
  1886. X            }
  1887. X            if (type == PUNCT &&
  1888. X            (token[0] == '}' && token[1] == '\0'))
  1889. X            break;
  1890. X            if (type == 1){
  1891. X            /* this is an enumerated label */
  1892. X            if (np->enums == 0){
  1893. X                ep = np->enums = (struct enum_list *)
  1894. X                    Malloc(sizeof(struct enum_list));
  1895. X            } else {
  1896. X                ep->next = (struct enum_list *)
  1897. X                    Malloc(sizeof(struct enum_list));
  1898. X                ep = ep->next;
  1899. X            }
  1900. X            ep->next = 0;
  1901. X            /* a reasonable approximation for the length */
  1902. X            ep->label = (char *)Malloc((unsigned)strlen(token));
  1903. X            cp = ep->label;
  1904. X            tp = token;
  1905. X            while(*tp != '(' && *tp != 0)
  1906. X                *cp++ = *tp++;
  1907. X            *cp = 0;
  1908. X            if (*tp == 0){
  1909. X                type = get_token(fp, token);
  1910. X                if (type != LABEL){
  1911. X                print_error("Expected \"(\"", (char *)NULL);
  1912. X                free_node(np);
  1913. X                return 0;
  1914. X                }
  1915. X                tp = token;
  1916. X            }
  1917. X            if (*tp == '('){
  1918. X                tp++;
  1919. X            } else {
  1920. X                print_error("Expected \"(\"", token);
  1921. X                free_node(np);
  1922. X                return 0;
  1923. X            }
  1924. X            if (*tp == 0){
  1925. X                type = get_token(fp, token);
  1926. X                if (type != LABEL){
  1927. X                print_error("Expected integer", token);
  1928. X                free_node(np);
  1929. X                return 0;
  1930. X                }
  1931. X                tp = token;
  1932. X            }
  1933. X
  1934. X            cp = tp;
  1935. X            if (!isdigit(*cp)){
  1936. X                print_error("Expected integer", token);
  1937. X                free_node(np);
  1938. X                return 0;
  1939. X            }
  1940. X            while(isdigit(*tp) && *tp != 0)
  1941. X                tp++;
  1942. X            if (*tp == ')')
  1943. X                *tp = '\0';    /* terminate number */
  1944. X            else if (*tp == 0){
  1945. X                type = get_token(fp, token);
  1946. X                if (type != LABEL || *token != ')'){
  1947. X                print_error("Expected \")\"", token);
  1948. X                free_node(np);
  1949. X                return 0;
  1950. X                }
  1951. X            } else {
  1952. X                print_error("Expected \")\"", token);
  1953. X                free_node(np);
  1954. X                return 0;
  1955. X            }
  1956. X            ep->value = atoi(cp);
  1957. X            }
  1958. X        }
  1959. X        if (type == NULL){
  1960. X            print_error("Premature end of file", (char *)NULL);
  1961. X            free_node(np);
  1962. X            return 0;
  1963. X        }
  1964. X        nexttype = get_token(fp, nexttoken);
  1965. X        } else if (nexttype == LABEL && *nexttoken == '('){
  1966. X        /* ignore the "constrained integer" for now */
  1967. X        nexttype = get_token(fp, nexttoken);
  1968. X        }
  1969. X        break;
  1970. X    case OBJID:
  1971. X    case OCTETSTR:
  1972. X    case NETADDR:
  1973. X    case IPADDR:
  1974. X    case COUNTER:
  1975. X    case GAUGE:
  1976. X    case TIMETICKS:
  1977. X    case OPAQUE:
  1978. X    case NUL:
  1979. X    case LABEL:
  1980. X        strcpy(syntax, token);
  1981. X        break;
  1982. X    default:
  1983. X        print_error("Bad syntax", token);
  1984. X        free_node(np);
  1985. X        return 0;
  1986. X    }
  1987. X    if (nexttype != ACCESS){
  1988. X    print_error("Should be ACCESS", nexttoken);
  1989. X    free_node(np);
  1990. X    return 0;
  1991. X    }
  1992. X    type = get_token(fp, token);
  1993. X    if (type != READONLY && type != READWRITE && type != WRITEONLY
  1994. X    && type != NOACCESS){
  1995. X    print_error("Bad access type", nexttoken);
  1996. X    free_node(np);
  1997. X    return 0;
  1998. X    }
  1999. X    type = get_token(fp, token);
  2000. X    if (type != STATUS){
  2001. X    print_error("Should be STATUS", token);
  2002. X    free_node(np);
  2003. X    return 0;
  2004. X    }
  2005. X    type = get_token(fp, token);
  2006. X    if (type != MANDATORY && type != OPTIONAL && type != OBSOLETE && type != RECOMMENDED){
  2007. X    print_error("Bad status", token);
  2008. X    free_node(np);
  2009. X    return 0;
  2010. X    }
  2011. X    type = get_token(fp, token);
  2012. X    if (type != EQUALS){
  2013. X    print_error("Bad format", token);
  2014. X    free_node(np);
  2015. X    return 0;
  2016. X    }
  2017. X    length = getoid(fp, oid, 16);
  2018. X    if (length > 1 && length <= 16){
  2019. X    /* just take the last pair in the oid list */
  2020. X    if (oid[length - 2].label)
  2021. X        strncpy(np->parent, oid[length - 2].label, 32);
  2022. X    strcpy(np->label, name);
  2023. X    if (oid[length - 1].subid != -1)
  2024. X        np->subid = oid[length - 1].subid;
  2025. X    else
  2026. X        print_error("Warning: This entry is pretty silly", (char *)NULL);
  2027. X    } else {
  2028. X    print_error("No end to oid", (char *)NULL);
  2029. X    free_node(np);
  2030. X    np = 0;
  2031. X    }
  2032. X    /* free oid array */
  2033. X    for(count = 0; count < length; count++){
  2034. X    if (oid[count].label)
  2035. X        free(oid[count].label);
  2036. X    oid[count].label = 0;
  2037. X    }
  2038. X    return np;
  2039. X}
  2040. X
  2041. X
  2042. X/*
  2043. X * Parses a mib file and returns a linked list of nodes found in the file.
  2044. X * Returns NULL on error.
  2045. X */
  2046. Xstatic struct node *
  2047. Xparse(fp)
  2048. X    FILE *fp;
  2049. X{
  2050. X    char token[64];
  2051. X    char name[32];
  2052. X    int    type = 1;
  2053. X    struct node *np, *root = NULL;
  2054. X
  2055. X    hash_init();
  2056. X
  2057. X    while(type != NULL){
  2058. X    type = get_token(fp, token);
  2059. X    if (type != LABEL){
  2060. X        if (type == NULL){
  2061. X        return root;
  2062. X        }
  2063. X        print_error(token, "is a reserved word");
  2064. X        return NULL;
  2065. X    }
  2066. X    strncpy(name, token, 32);
  2067. X    type = get_token(fp, token);
  2068. X    if (type == OBJTYPE){
  2069. X        if (root == NULL){
  2070. X        /* first link in chain */
  2071. X        np = root = parse_objecttype(fp, name);
  2072. X        if (np == NULL){
  2073. X            print_error("Bad parse of object type", (char *)NULL);
  2074. X            return NULL;
  2075. X        }
  2076. X        } else {
  2077. X        np->next = parse_objecttype(fp, name);
  2078. X        if (np->next == NULL){
  2079. X            print_error("Bad parse of objecttype", (char *)NULL);
  2080. X            return NULL;
  2081. X        }
  2082. X        }
  2083. X        /* now find end of chain */
  2084. X        while(np->next)
  2085. X        np = np->next;
  2086. X    } else if (type == OBJID){
  2087. X        if (root == NULL){
  2088. X        /* first link in chain */
  2089. X        np = root = parse_objectid(fp, name);
  2090. X        if (np == NULL){
  2091. X            print_error("Bad parse of object id", (char *)NULL);
  2092. X            return NULL;
  2093. X        }
  2094. X        } else {
  2095. X        np->next = parse_objectid(fp, name);
  2096. X        if (np->next == NULL){
  2097. X            print_error("Bad parse of object type", (char *)NULL);
  2098. X            return NULL;
  2099. X        }
  2100. X        }
  2101. X        /* now find end of chain */
  2102. X        while(np->next)
  2103. X        np = np->next;
  2104. X    } else if (type == EQUALS){
  2105. X        type = parse_asntype(fp);
  2106. X    } else if (type == NULL){
  2107. X        break;
  2108. X    } else {
  2109. X        print_error("Bad operator", (char *)NULL);
  2110. X        return NULL;
  2111. X    }
  2112. X    }
  2113. X#ifdef TEST
  2114. X{
  2115. X    struct enum_list *ep;
  2116. X    
  2117. X    for(np = root; np; np = np->next){
  2118. X    printf("%s ::= { %s %d } (%d)\n", np->label, np->parent, np->subid,
  2119. X        np->type);
  2120. X    if (np->enums){
  2121. X        printf("Enums: \n");
  2122. X        for(ep = np->enums; ep; ep = ep->next){
  2123. X        printf("%s(%d)\n", ep->label, ep->value);
  2124. X        }
  2125. X    }
  2126. X    }
  2127. X}
  2128. X#endif /* TEST */
  2129. X    return root;
  2130. X}
  2131. X
  2132. X/*
  2133. X * Parses a token from the file.  The type of the token parsed is returned,
  2134. X * and the text is placed in the string pointed to by token.
  2135. X */
  2136. Xstatic int
  2137. Xget_token(fp, token)
  2138. X    register FILE *fp;
  2139. X    register char *token;
  2140. X{
  2141. X    static char last = ' ';
  2142. X    register int ch;
  2143. X    register char *cp = token;
  2144. X    register int hash = 0;
  2145. X    register struct tok *tp;
  2146. X
  2147. X    *cp = 0;
  2148. X    ch = last;
  2149. X    /* skip all white space */
  2150. X    while(isspace(ch) && ch != -1){
  2151. X    ch = getc(fp);
  2152. X    if (ch == '\n')
  2153. X        Line++;
  2154. X    }
  2155. X    if (ch == -1)
  2156. X    return NULL;
  2157. X
  2158. X    /*
  2159. X     * Accumulate characters until white space is found.  Then attempt to match this
  2160. X     * token as a reserved word.  If a match is found, return the type.  Else it is
  2161. X     * a label.
  2162. X     */
  2163. X    do {
  2164. X    if (!isspace(ch)){
  2165. X        hash += ch;
  2166. X        *cp++ = ch;
  2167. X        if (ch == '\n')
  2168. X        Line++;
  2169. X    } else {
  2170. X        last = ch;
  2171. X        *cp = '\0';
  2172. X
  2173. X        for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) {
  2174. X        if ((tp->hash == hash) && (strcmp(tp->name, token) == 0))
  2175. X            break;
  2176. X        }
  2177. X        if (tp){
  2178. X        if (tp->token == CONTINUE)
  2179. X            continue;
  2180. X        return (tp->token);
  2181. X        }
  2182. X
  2183. X        if (token[0] == '-' && token[1] == '-'){
  2184. X        /* strip comment */
  2185. X        while ((ch = getc(fp)) != -1)
  2186. X            if (ch == '\n'){
  2187. X            Line++;
  2188. X            break;
  2189. X            }
  2190. X        if (ch == -1)
  2191. X            return NULL;
  2192. X        last = ch;
  2193. X        return get_token(fp, token);        
  2194. X        }
  2195. X        return LABEL;
  2196. X    }
  2197. X    
  2198. X    } while ((ch = getc(fp)) != -1);
  2199. X    return NULL;
  2200. X}
  2201. X
  2202. Xstruct tree *
  2203. Xread_mib(filename)
  2204. X    char *filename;
  2205. X{
  2206. X    FILE *fp;
  2207. X    struct node *nodes;
  2208. X    struct tree *tree;
  2209. X    struct node *parse();
  2210. X
  2211. X    fp = fopen(filename, "r");
  2212. X    if (fp == NULL)
  2213. X    return NULL;
  2214. X    nodes = parse(fp);
  2215. X    if (!nodes){
  2216. X    fprintf(stderr, "Mib table is bad.  Exiting\n");
  2217. X    exit(1);
  2218. X    }
  2219. X    tree = build_tree(nodes);
  2220. X    fclose(fp);
  2221. X    return tree;
  2222. X}
  2223. X
  2224. X
  2225. X#ifdef TEST
  2226. Xmain(argc, argv)
  2227. X    int argc;
  2228. X    char *argv[];
  2229. X{
  2230. X    FILE *fp;
  2231. X    struct node *nodes;
  2232. X    struct tree *tp;
  2233. X
  2234. X    fp = fopen("mib.txt", "r");
  2235. X    if (fp == NULL){
  2236. X    fprintf(stderr, "open failed\n");
  2237. X    return 1;
  2238. X    }
  2239. X    nodes = parse(fp);
  2240. X    tp = build_tree(nodes);
  2241. X    print_subtree(tp, 0);
  2242. X    fclose(fp);
  2243. X}
  2244. X
  2245. X#endif /* TEST */
  2246. END_OF_FILE
  2247.   if test 22322 -ne `wc -c <'netramet/src/snmplib/parse.c'`; then
  2248.     echo shar: \"'netramet/src/snmplib/parse.c'\" unpacked with wrong size!
  2249.   fi
  2250.   # end of 'netramet/src/snmplib/parse.c'
  2251. fi
  2252. echo shar: End of archive 17 \(of 25\).
  2253. cp /dev/null ark17isdone
  2254. MISSING=""
  2255. 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
  2256.     if test ! -f ark${I}isdone ; then
  2257.     MISSING="${MISSING} ${I}"
  2258.     fi
  2259. done
  2260. if test "${MISSING}" = "" ; then
  2261.     echo You have unpacked all 25 archives.
  2262.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2263. else
  2264.     echo You still must unpack the following archives:
  2265.     echo "        " ${MISSING}
  2266. fi
  2267. exit 0
  2268. exit 0 # Just in case...
  2269.