Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1270 lines
36 KiB

  1. // wsnmp_bn.c
  2. //
  3. // WinSNMP Low-Level SNMP/ASN.1/BER Functions and helpers
  4. // Copyright 1995-1997 ACE*COMM Corp
  5. // Rleased to Microsoft under Contract
  6. // Beta 1 version, 970228
  7. // Bob Natale ([email protected])
  8. //
  9. // 980424 - Received msgLen may be larger than pduLen
  10. // - ParsePduHdr() and ParseMessage() now accommodate this.
  11. // 980420 - Mods related to ParseCntr64() inspired by
  12. // MS bug ID 127357 (removal of temp64 variable)
  13. // - Mod to ParseOID() for MS bug ID 127353
  14. // (reset os_ptr->ptr to NULL on error)
  15. //
  16. // 970310 - Typographical changes
  17. //
  18. #include "winsnmp.inc"
  19. long FindLenVarBind (LPVARBIND vb_ptr);
  20. long FindLenVALUE (smiLPVALUE);
  21. long FindLenOctetString (smiLPOCTETS os_ptr);
  22. long FindLenOID (smiLPCOID oid_ptr);
  23. long FindLenUInt (smiUINT32 value);
  24. long FindLenInt (smiINT32 value);
  25. long FindLenCntr64 (smiLPCNTR64 value);
  26. long DoLenLen (smiINT32 len);
  27. void AddLen (smiLPBYTE *tmpPtr, smiINT32 lenlen, smiINT32 data_len);
  28. long AddVarBind (smiLPBYTE *tmpPtr, LPVARBIND vb_ptr);
  29. long AddOctetString (smiLPBYTE *tmpPtr, int type, smiLPOCTETS os_ptr);
  30. long AddOID (smiLPBYTE *tmpPtr, smiLPOID oid_ptr);
  31. long AddUInt (smiLPBYTE *tmpPtr, int type, smiUINT32 value);
  32. long AddInt (smiLPBYTE *tmpPtr, smiINT32 value);
  33. long AddCntr64 (smiLPBYTE *tmpPtr, smiLPCNTR64 value);
  34. void AddNull (smiLPBYTE *tmpPtr, int type);
  35. LPVARBIND ParseVarBind (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen);
  36. BOOL ParseOctetString (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen, smiLPOCTETS os_ptr);
  37. BOOL ParseOID (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen, smiLPOID oid_ptr);
  38. BOOL ParseCntr64 (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen, smiLPCNTR64 cntr64_ptr);
  39. BOOL ParseUInt (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen, smiLPUINT32 value);
  40. BOOL ParseInt (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen, smiLPINT value);
  41. BOOL ParseNull (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen);
  42. BOOL ParseSequence (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen);
  43. smiINT32 ParseType (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen);
  44. smiINT32 ParseLength (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen);
  45. void FreeOctetString (smiLPOCTETS os_ptr)
  46. {
  47. if (os_ptr)
  48. {
  49. if (os_ptr->ptr)
  50. GlobalFree (os_ptr->ptr);
  51. GlobalFree (os_ptr);
  52. }
  53. return;
  54. }
  55. void FreeVarBindList (LPVARBIND vb_ptr)
  56. {
  57. if (vb_ptr)
  58. { // NULLs are handled by downstream call
  59. FreeVarBindList (vb_ptr->next_var);
  60. FreeVarBind (vb_ptr);
  61. }
  62. return;
  63. }
  64. void FreeVarBind (LPVARBIND vb_ptr)
  65. {
  66. if (vb_ptr)
  67. {
  68. if (vb_ptr->name.ptr)
  69. GlobalFree (vb_ptr->name.ptr);
  70. switch (vb_ptr->value.syntax)
  71. {
  72. case SNMP_SYNTAX_OID:
  73. if (vb_ptr->value.value.oid.ptr)
  74. GlobalFree (vb_ptr->value.value.oid.ptr);
  75. break;
  76. case SNMP_SYNTAX_OCTETS:
  77. case SNMP_SYNTAX_IPADDR:
  78. case SNMP_SYNTAX_OPAQUE:
  79. if (vb_ptr->value.value.string.ptr)
  80. GlobalFree (vb_ptr->value.value.string.ptr);
  81. break;
  82. default: // Remaining types do not have 'ptr' members
  83. break;
  84. } // end_switch
  85. GlobalFree (vb_ptr);
  86. } // end_if (vb_ptr)
  87. return;
  88. } // end_FreeVarBind
  89. void FreeV1Trap (LPV1TRAP v1Trap_ptr)
  90. {
  91. if (v1Trap_ptr)
  92. {
  93. if (v1Trap_ptr->enterprise.ptr)
  94. GlobalFree (v1Trap_ptr->enterprise.ptr);
  95. if (v1Trap_ptr->agent_addr.ptr)
  96. GlobalFree (v1Trap_ptr->agent_addr.ptr);
  97. GlobalFree (v1Trap_ptr);
  98. }
  99. } // end_FreeV1Trap
  100. void AddLen (smiLPBYTE *tmpPtr, long lenlen, long data_len)
  101. {
  102. long i;
  103. if (lenlen == 1)
  104. *(*tmpPtr)++ = (smiBYTE)data_len;
  105. else
  106. {
  107. *(*tmpPtr)++ = (smiBYTE)(0x80 + lenlen - 1);
  108. for (i = 1; i < lenlen; i++)
  109. {
  110. *(*tmpPtr)++ = (smiBYTE)((data_len >>
  111. (8 * (lenlen - i - 1))) & 0xFF);
  112. } // end_for
  113. } // end_else
  114. return;
  115. } // end_AddLen
  116. long AddVarBind (smiLPBYTE *tmpPtr, LPVARBIND vb_ptr)
  117. {
  118. long lenlen;
  119. if (vb_ptr == NULL)
  120. return (0);
  121. if ((lenlen = DoLenLen(vb_ptr->data_length)) == -1)
  122. return (-1);
  123. *(*tmpPtr)++ = SNMP_SYNTAX_SEQUENCE;
  124. AddLen (tmpPtr, lenlen, vb_ptr->data_length);
  125. if (AddOID (tmpPtr, &vb_ptr->name) == -1)
  126. return (-1);
  127. switch (vb_ptr->value.syntax)
  128. {
  129. case SNMP_SYNTAX_CNTR32:
  130. case SNMP_SYNTAX_GAUGE32:
  131. case SNMP_SYNTAX_TIMETICKS:
  132. case SNMP_SYNTAX_UINT32:
  133. AddUInt (tmpPtr, (int)vb_ptr->value.syntax, vb_ptr->value.value.uNumber);
  134. break;
  135. case SNMP_SYNTAX_INT:
  136. AddInt (tmpPtr, vb_ptr->value.value.sNumber);
  137. break;
  138. case SNMP_SYNTAX_OID:
  139. if (AddOID (tmpPtr, (smiLPOID)&(vb_ptr->value.value.oid)) == -1)
  140. return (-1);
  141. break;
  142. case SNMP_SYNTAX_CNTR64:
  143. AddCntr64 (tmpPtr, (smiLPCNTR64)&(vb_ptr->value.value.hNumber));
  144. break;
  145. case SNMP_SYNTAX_OCTETS:
  146. case SNMP_SYNTAX_IPADDR:
  147. case SNMP_SYNTAX_OPAQUE:
  148. if (AddOctetString (tmpPtr, (int)vb_ptr->value.syntax,
  149. (smiLPOCTETS)&(vb_ptr->value.value.string)) == -1)
  150. return -1;
  151. break;
  152. case SNMP_SYNTAX_NULL:
  153. case SNMP_SYNTAX_NOSUCHOBJECT:
  154. case SNMP_SYNTAX_NOSUCHINSTANCE:
  155. case SNMP_SYNTAX_ENDOFMIBVIEW:
  156. AddNull (tmpPtr, (int)vb_ptr->value.syntax);
  157. break;
  158. default:
  159. return (-1);
  160. } // end_switch
  161. return (AddVarBind (tmpPtr, vb_ptr->next_var));
  162. }
  163. long AddOctetString (smiLPBYTE *tmpPtr, int type, smiLPOCTETS os_ptr)
  164. {
  165. UINT i;
  166. long lenlen;
  167. if ((lenlen = DoLenLen ((long)os_ptr->len)) == -1)
  168. return (-1);
  169. *(*tmpPtr)++ = (smiBYTE)(0xFF & type);
  170. AddLen (tmpPtr, lenlen, os_ptr->len);
  171. for (i = 0; i < os_ptr->len; i++)
  172. *(*tmpPtr)++ = os_ptr->ptr[i];
  173. return (0);
  174. }
  175. long AddOID (smiLPBYTE *tmpPtr, smiLPOID oid_ptr)
  176. {
  177. UINT i;
  178. long lenlen = 0;
  179. long encoded_len;
  180. encoded_len = 1; // for first two SID's
  181. for (i = 2; i < oid_ptr->len; i++)
  182. {
  183. if (oid_ptr->ptr[i] < 0x80) // 0 - 0x7F
  184. encoded_len += 1;
  185. else if (oid_ptr->ptr[i] < 0x4000) // 0x80 - 0x3FFF
  186. encoded_len += 2;
  187. else if (oid_ptr->ptr[i] < 0x200000) // 0x4000 - 0x1FFFFF
  188. encoded_len += 3;
  189. else if (oid_ptr->ptr[i] < 0x10000000) // 0x200000 - 0xFFFFFFF
  190. encoded_len += 4;
  191. else
  192. encoded_len += 5;
  193. }
  194. if ((lenlen = DoLenLen (encoded_len)) == -1)
  195. return (-1);
  196. *(*tmpPtr)++ = (smiBYTE)(0xFF & SNMP_SYNTAX_OID);
  197. AddLen (tmpPtr, lenlen, encoded_len);
  198. if (oid_ptr->len < 2)
  199. *(*tmpPtr)++ = (smiBYTE)(oid_ptr->ptr[0] * 40);
  200. else
  201. *(*tmpPtr)++ = (smiBYTE)((oid_ptr->ptr[0] * 40) + oid_ptr->ptr[1]);
  202. for (i = 2; i < oid_ptr->len; i++)
  203. {
  204. if (oid_ptr->ptr[i] < 0x80)
  205. { // 0 - 0x7F
  206. *(*tmpPtr)++ = (smiBYTE)oid_ptr->ptr[i];
  207. }
  208. else if (oid_ptr->ptr[i] < 0x4000)
  209. { // 0x80 - 0x3FFF
  210. *(*tmpPtr)++ = (smiBYTE)
  211. (((oid_ptr->ptr[i]) >> 7) | 0x80); // set high bit
  212. *(*tmpPtr)++ = (smiBYTE)(oid_ptr->ptr[i] & 0x7f);
  213. }
  214. else if (oid_ptr->ptr[i] < 0x200000)
  215. { // 0x4000 - 0x1FFFFF
  216. *(*tmpPtr)++ = (smiBYTE)
  217. (((oid_ptr->ptr[i]) >> 14) | 0x80); // set high bit
  218. *(*tmpPtr)++ = (smiBYTE)
  219. (((oid_ptr->ptr[i]) >> 7) | 0x80); // set high bit
  220. *(*tmpPtr)++ = (smiBYTE)(oid_ptr->ptr[i] & 0x7f);
  221. }
  222. else if (oid_ptr->ptr[i] < 0x10000000)
  223. { // 0x200000 - 0xFFFFFFF
  224. *(*tmpPtr)++ = (smiBYTE)
  225. (((oid_ptr->ptr[i]) >> 21) | 0x80); // set high bit
  226. *(*tmpPtr)++ = (smiBYTE)
  227. (((oid_ptr->ptr[i]) >> 14) | 0x80); // set high bit
  228. *(*tmpPtr)++ = (smiBYTE)
  229. (((oid_ptr->ptr[i]) >> 7) | 0x80); // set high bit
  230. *(*tmpPtr)++ = (smiBYTE)(oid_ptr->ptr[i] & 0x7f);
  231. }
  232. else
  233. {
  234. *(*tmpPtr)++ = (smiBYTE)
  235. (((oid_ptr->ptr[i]) >> 28) | 0x80); // set high bit
  236. *(*tmpPtr)++ = (smiBYTE)
  237. (((oid_ptr->ptr[i]) >> 21) | 0x80); // set high bit
  238. *(*tmpPtr)++ = (smiBYTE)
  239. (((oid_ptr->ptr[i]) >> 14) | 0x80); // set high bit
  240. *(*tmpPtr)++ = (smiBYTE)
  241. (((oid_ptr->ptr[i]) >> 7) | 0x80); // set high bit
  242. *(*tmpPtr)++ = (smiBYTE)(oid_ptr->ptr[i] & 0x7f);
  243. }
  244. } // end_for
  245. return (0);
  246. } // end_AddOID
  247. long AddUInt (smiLPBYTE *tmpPtr, int type, smiUINT32 value)
  248. {
  249. long i;
  250. long datalen;
  251. long lenlen;
  252. // if high bit one, must use 5 octets (first with 00)
  253. if (((value >> 24) & 0xFF) != 0)
  254. datalen = 4;
  255. else if (((value >> 16) & 0xFF) != 0)
  256. datalen = 3;
  257. else if (((value >> 8) & 0xFF) != 0)
  258. datalen = 2;
  259. else
  260. datalen = 1;
  261. if (((value >> (8 * (datalen - 1))) & 0x80) != 0)
  262. datalen++;
  263. lenlen = 1; // < 127 octets
  264. *(*tmpPtr)++ = (smiBYTE)(0xFF & type);
  265. AddLen(tmpPtr, lenlen, datalen);
  266. if (datalen == 5)
  267. { // gotta put a 00 in first octet
  268. *(*tmpPtr)++ = (smiBYTE)0;
  269. for (i = 1; i < datalen; i++)
  270. {
  271. *(*tmpPtr)++ = (smiBYTE)(value >>
  272. (8 * ((datalen - 1) - i) & 0xFF));
  273. }
  274. } // end_if
  275. else
  276. {
  277. for (i = 0; i < datalen; i++)
  278. {
  279. *(*tmpPtr)++ = (smiBYTE)(value >>
  280. (8 * ((datalen - 1) - i) & 0xFF));
  281. }
  282. } // end_else
  283. return (0);
  284. } // end_AddUInt
  285. long AddInt (smiLPBYTE *tmpPtr, smiINT32 value)
  286. {
  287. long i;
  288. long datalen;
  289. long lenlen;
  290. switch ((smiBYTE) ((value >> 24) & 0xFF))
  291. {
  292. case 0x00:
  293. if (((value >> 16) & 0xFF) != 0)
  294. datalen = 3;
  295. else if (((value >> 8) & 0xFF) != 0)
  296. datalen = 2;
  297. else
  298. datalen = 1;
  299. if (((value >> (8 * (datalen - 1))) & 0x80) != 0)
  300. datalen++;
  301. break;
  302. case 0xFF:
  303. if (((value >> 16) & 0xFF) != 0xFF)
  304. datalen = 3;
  305. else if (((value >> 8) & 0xFF) != 0xFF)
  306. datalen = 2;
  307. else
  308. datalen = 1;
  309. if (((value >> (8 * (datalen - 1))) & 0x80) == 0)
  310. datalen++;
  311. break;
  312. default:
  313. datalen = 4;
  314. } // end_switch
  315. lenlen = 1; // < 127 octets
  316. *(*tmpPtr)++ = (smiBYTE)(0xFF & SNMP_SYNTAX_INT);
  317. AddLen(tmpPtr, lenlen, datalen);
  318. for (i = 0; i < datalen; i++)
  319. {
  320. *(*tmpPtr)++ = (smiBYTE) (value >>
  321. (8 * ((datalen - 1) - i) & 0xFF));
  322. }
  323. return (0);
  324. } // end_AddInt()
  325. long AddCntr64 (smiLPBYTE *tmpPtr, smiLPCNTR64 value)
  326. {
  327. long i;
  328. long datalen;
  329. long lenlen;
  330. datalen = FindLenCntr64(value) - 2;
  331. lenlen = 1; // < 127 octets
  332. *(*tmpPtr)++ = (smiBYTE)(0xFF & SNMP_SYNTAX_CNTR64);
  333. AddLen(tmpPtr, lenlen, datalen);
  334. if (datalen == 9)
  335. { // gotta put a 00 in first octet
  336. *(*tmpPtr)++ = (smiBYTE)0;
  337. datalen--;
  338. }
  339. for (i = datalen; i > 4; i--)
  340. {
  341. *(*tmpPtr)++ = (smiBYTE)(value->hipart >>
  342. (8 * (i - 5) & 0xFF));
  343. }
  344. for (; i > 0; i--)
  345. {
  346. *(*tmpPtr)++ = (smiBYTE)(value->lopart >>
  347. (8 * (i - 1) & 0xFF));
  348. }
  349. return (0);
  350. }
  351. long FindLenVarBind (LPVARBIND vb_ptr)
  352. {
  353. long lenlen;
  354. long tot_so_far;
  355. long lOidLen;
  356. long lValueLen;
  357. if (!vb_ptr) return (0);
  358. tot_so_far = FindLenVarBind (vb_ptr->next_var);
  359. if (tot_so_far == -1)
  360. return (-1);
  361. if ((lOidLen = FindLenOID (&vb_ptr->name)) == -1)
  362. return (-1);
  363. if ((lValueLen = FindLenVALUE (&vb_ptr->value)) == -1)
  364. return (-1);
  365. vb_ptr->data_length = lOidLen +
  366. lValueLen;
  367. if ((lenlen = DoLenLen (vb_ptr->data_length)) == -1)
  368. return (-1);
  369. return (1 + lenlen + vb_ptr->data_length + tot_so_far);
  370. } // end_FindLenVarBind
  371. long FindLenVALUE (smiLPVALUE value_ptr)
  372. {
  373. if (value_ptr)
  374. {
  375. switch (value_ptr->syntax)
  376. {
  377. case SNMP_SYNTAX_OCTETS:
  378. case SNMP_SYNTAX_IPADDR:
  379. case SNMP_SYNTAX_OPAQUE:
  380. return (FindLenOctetString (&value_ptr->value.string));
  381. case SNMP_SYNTAX_OID:
  382. return (FindLenOID (&value_ptr->value.oid));
  383. case SNMP_SYNTAX_NULL:
  384. case SNMP_SYNTAX_NOSUCHOBJECT:
  385. case SNMP_SYNTAX_NOSUCHINSTANCE:
  386. case SNMP_SYNTAX_ENDOFMIBVIEW:
  387. return (2);
  388. case SNMP_SYNTAX_INT:
  389. return (FindLenInt (value_ptr->value.sNumber));
  390. case SNMP_SYNTAX_CNTR32:
  391. case SNMP_SYNTAX_GAUGE32:
  392. case SNMP_SYNTAX_TIMETICKS:
  393. case SNMP_SYNTAX_UINT32:
  394. return (FindLenUInt (value_ptr->value.uNumber));
  395. case SNMP_SYNTAX_CNTR64:
  396. return (FindLenCntr64 (&value_ptr->value.hNumber));
  397. } // end_switch
  398. } // end_if
  399. return (-1);
  400. } // end_FindLenVALUE
  401. long FindLenOctetString (smiLPOCTETS os_ptr)
  402. {
  403. long lenlen;
  404. if (!os_ptr) return (-1);
  405. if ((lenlen = DoLenLen (os_ptr->len)) == -1)
  406. return (-1);
  407. return (1 + lenlen + os_ptr->len);
  408. }
  409. long FindLenOID (smiLPCOID oid_ptr)
  410. {
  411. long lenlen;
  412. UINT i;
  413. UINT encoded_len;
  414. encoded_len = 1; // for first two Sub-IDs
  415. // beware of i = 2
  416. for (i = 2; i < oid_ptr->len; i++)
  417. {
  418. if (oid_ptr->ptr[i] < 0x80) // 0 - 0x7F
  419. encoded_len += 1;
  420. else if (oid_ptr->ptr[i] < 0x4000) // 0x80 - 0x3FFF
  421. encoded_len += 2;
  422. else if (oid_ptr->ptr[i] < 0x200000) // 0x4000 - 0x1FFFFF
  423. encoded_len += 3;
  424. else if (oid_ptr->ptr[i] < 0x10000000) // 0x200000 - 0xFFFFFFF
  425. encoded_len += 4;
  426. else
  427. encoded_len += 5;
  428. } // end_for
  429. if ((lenlen = DoLenLen (encoded_len)) == -1)
  430. return (-1);
  431. return (1 + lenlen + encoded_len);
  432. } // end_FindLenOID
  433. long FindLenUInt (smiUINT32 value)
  434. {
  435. long datalen;
  436. // if high bit one, must use 5 octets (first with 00)
  437. if (((value >> 24) & 0xFF) != 0)
  438. datalen = 4;
  439. else if (((value >> 16) & 0xFF) != 0)
  440. datalen = 3;
  441. else if (((value >> 8) & 0xFF) != 0)
  442. datalen = 2;
  443. else
  444. datalen = 1;
  445. if (((value >> (8 * (datalen - 1))) & 0x80) != 0)
  446. datalen++;
  447. // length of length < 127 octets
  448. return (1 + 1 + datalen);
  449. }
  450. long FindLenInt (smiINT32 value)
  451. {
  452. long datalen;
  453. switch ((smiBYTE) ((value >> 24) & 0xFF))
  454. {
  455. case 0x00:
  456. if (((value >> 16) & 0xFF) != 0)
  457. datalen = 3;
  458. else if (((value >> 8) & 0xFF) != 0)
  459. datalen = 2;
  460. else
  461. datalen = 1;
  462. if (((value >> (8 * (datalen - 1))) & 0x80) != 0)
  463. datalen++;
  464. break;
  465. case 0xFF:
  466. if (((value >> 16) & 0xFF) != 0xFF)
  467. datalen = 3;
  468. else if (((value >> 8) & 0xFF) != 0xFF)
  469. datalen = 2;
  470. else
  471. datalen = 1;
  472. if (((value >> (8 * (datalen - 1))) & 0x80) == 0)
  473. datalen++;
  474. break;
  475. default:
  476. datalen = 4;
  477. } // end_switch
  478. return (1 + 1 + datalen);
  479. }
  480. long FindLenCntr64 (smiLPCNTR64 value)
  481. {
  482. long datalen;
  483. // if high bit one, must use 5 octets (first with 00)
  484. if (((value->hipart >> 24) & 0xFF) != 0)
  485. {
  486. datalen = 8;
  487. if (((value->hipart >> 24) & 0x80) != 0) datalen++;
  488. }
  489. else if (((value->hipart >> 16) & 0xFF) != 0)
  490. {
  491. datalen = 7;
  492. if (((value->hipart >> 16) & 0x80) != 0) datalen++;
  493. }
  494. else if (((value->hipart >> 8) & 0xFF) != 0)
  495. {
  496. datalen = 6;
  497. if (((value->hipart >> 8) & 0x80) != 0) datalen++;
  498. }
  499. else if (((value->hipart) & 0xFF) != 0)
  500. {
  501. datalen = 5;
  502. if (((value->hipart) & 0x80) != 0) datalen++;
  503. }
  504. else if (((value->lopart>> 24) & 0xFF) != 0)
  505. {
  506. datalen = 4;
  507. if (((value->lopart >> 24) & 0x80) != 0) datalen++;
  508. }
  509. else if (((value->lopart >> 16) & 0xFF) != 0)
  510. {
  511. datalen = 3;
  512. if (((value->lopart >> 16) & 0x80) != 0) datalen++;
  513. }
  514. else if (((value->lopart >> 8) & 0xFF) != 0)
  515. {
  516. datalen = 2;
  517. if (((value->lopart >> 8) & 0x80) != 0) datalen++;
  518. }
  519. else
  520. {
  521. datalen = 1;
  522. if (((value->lopart) & 0x80) != 0) datalen++;
  523. }
  524. // length of length < 127 octets
  525. return (1 + 1 + datalen);
  526. }
  527. long DoLenLen (long len)
  528. {
  529. // short form?
  530. if (len < 128) return (1);
  531. if (len < 0x100) return (2);
  532. if (len < 0x10000) return (3);
  533. if (len < 0x1000000) return (4);
  534. return (-1);
  535. }
  536. void AddNull (smiLPBYTE *tmpPtr, int type)
  537. {
  538. *(*tmpPtr)++ = (smiBYTE)(0xFF & type);
  539. *(*tmpPtr)++ = 0x00;
  540. return;
  541. }
  542. BOOL BuildMessage (smiUINT32 version, smiLPOCTETS community,
  543. LPPDUS pdu, smiINT32 requestId,
  544. smiLPBYTE *msgAddr, smiLPUINT32 msgSize)
  545. {
  546. LPVARBIND vbList = NULL;
  547. long nVbDataLen, nVbLenLen, nVbTotalLen;
  548. long nPduDataLen, nPduLenLen, nPduTotalLen;
  549. long nMsgDataLen, nMsgLenLen, nMsgTotalLen;
  550. long nTmpDataLen;
  551. smiLPBYTE tmpPtr = NULL;
  552. *msgAddr = NULL;
  553. *msgSize = 0;
  554. if (pdu == NULL || community == NULL)
  555. return (FALSE);
  556. // Determine length of VarBind list part
  557. vbList = pdu->VBL_addr;
  558. if (vbList == NULL && pdu->VBL != 0)
  559. vbList = ((LPVBLS)snmpGetTableEntry(&VBLsDescr, HandleToUlong(pdu->VBL)-1))->vbList;
  560. // vbList == NULL is ok
  561. if ((nVbDataLen = FindLenVarBind (vbList)) == -1)
  562. return (FALSE);
  563. if ((nVbLenLen = DoLenLen (nVbDataLen)) == -1)
  564. return (FALSE);
  565. nVbTotalLen = 1 + nVbLenLen + nVbDataLen;
  566. // Determine length of PDU overhead part
  567. switch (pdu->type)
  568. {
  569. case SNMP_PDU_GET:
  570. case SNMP_PDU_GETNEXT:
  571. case SNMP_PDU_RESPONSE:
  572. case SNMP_PDU_SET:
  573. case SNMP_PDU_GETBULK:
  574. case SNMP_PDU_INFORM:
  575. case SNMP_PDU_TRAP:
  576. nPduDataLen = FindLenInt (requestId)
  577. + FindLenInt (pdu->errStatus)
  578. + FindLenInt (pdu->errIndex)
  579. + nVbTotalLen;
  580. break;
  581. case SNMP_PDU_V1TRAP:
  582. if (!pdu->v1Trap)
  583. return (FALSE);
  584. nPduDataLen = FindLenInt (pdu->v1Trap->generic_trap)
  585. + FindLenInt (pdu->v1Trap->specific_trap)
  586. + FindLenUInt (pdu->v1Trap->time_ticks)
  587. + nVbTotalLen;
  588. if ((nTmpDataLen = FindLenOID (&pdu->v1Trap->enterprise)) == -1)
  589. return (FALSE);
  590. nPduDataLen += nTmpDataLen;
  591. if ((nTmpDataLen = FindLenOctetString (&pdu->v1Trap->agent_addr)) == -1)
  592. return (FALSE);
  593. nPduDataLen += nTmpDataLen;
  594. break;
  595. default:
  596. return (FALSE);
  597. } // end_switch
  598. if ((nPduLenLen = DoLenLen(nPduDataLen)) == -1)
  599. return (FALSE);
  600. nPduTotalLen = 1 + nPduLenLen + nPduDataLen;
  601. if ((nTmpDataLen = FindLenOctetString (community)) == -1)
  602. return (FALSE);
  603. nMsgDataLen = FindLenUInt (version)
  604. + nTmpDataLen
  605. + nPduTotalLen;
  606. if ((nMsgLenLen = DoLenLen (nMsgDataLen)) == -1)
  607. return (FALSE);
  608. nMsgTotalLen = 1 + nMsgLenLen + nMsgDataLen;
  609. // Allocate the necessary memory for the message
  610. tmpPtr = GlobalAlloc (GPTR, nMsgTotalLen);
  611. if (tmpPtr == NULL)
  612. return (FALSE);
  613. *msgAddr = tmpPtr;
  614. *msgSize = nMsgTotalLen;
  615. // Now plug in the values in the message bytes
  616. *tmpPtr++ = SNMP_SYNTAX_SEQUENCE;
  617. // Wrapper portion
  618. AddLen (&tmpPtr, nMsgLenLen, nMsgDataLen);
  619. AddInt (&tmpPtr, version);
  620. if (AddOctetString (&tmpPtr, SNMP_SYNTAX_OCTETS, community) == -1)
  621. goto error_out;
  622. // PDU header portion
  623. // "Downgrade" GetBulk to GetNext if target is SNMPv1
  624. if (pdu->type == SNMP_PDU_GETBULK && version == 0)
  625. *tmpPtr++ = SNMP_PDU_GETNEXT;
  626. else
  627. *tmpPtr++ = (BYTE) pdu->type;
  628. AddLen (&tmpPtr, nPduLenLen, nPduDataLen);
  629. switch (pdu->type)
  630. {
  631. case SNMP_PDU_GET:
  632. case SNMP_PDU_GETNEXT:
  633. case SNMP_PDU_RESPONSE:
  634. case SNMP_PDU_SET:
  635. case SNMP_PDU_INFORM:
  636. case SNMP_PDU_TRAP:
  637. case SNMP_PDU_GETBULK:
  638. AddInt (&tmpPtr, requestId);
  639. AddInt (&tmpPtr, pdu->errStatus);
  640. AddInt (&tmpPtr, pdu->errIndex);
  641. break;
  642. case SNMP_PDU_V1TRAP:
  643. if (AddOID (&tmpPtr, &pdu->v1Trap->enterprise)== -1)
  644. goto error_out;
  645. if (AddOctetString (&tmpPtr, SNMP_SYNTAX_IPADDR, &pdu->v1Trap->agent_addr) == -1)
  646. goto error_out;
  647. AddInt (&tmpPtr, pdu->v1Trap->generic_trap);
  648. AddInt (&tmpPtr, pdu->v1Trap->specific_trap);
  649. AddUInt (&tmpPtr, SNMP_SYNTAX_TIMETICKS, pdu->v1Trap->time_ticks);
  650. break;
  651. default:
  652. goto error_out;
  653. } // end_switch
  654. // VarBindList portion
  655. *tmpPtr++ = SNMP_SYNTAX_SEQUENCE;
  656. AddLen (&tmpPtr, nVbLenLen, nVbDataLen);
  657. if (AddVarBind (&tmpPtr, vbList) == -1)
  658. {
  659. error_out:
  660. if (*msgAddr)
  661. GlobalFree (*msgAddr);
  662. *msgAddr = NULL;
  663. *msgSize = 0;
  664. return (FALSE);
  665. }
  666. // Success
  667. return (TRUE);
  668. } // end_BuildMessage()
  669. BOOL SetPduType (smiLPBYTE msgPtr, smiUINT32 msgLen, int pduType)
  670. {
  671. smiLPBYTE tmpPtr;
  672. smiINT32 tmp;
  673. if (!(tmpPtr = msgPtr)) // Deliberate assignment
  674. return (FALSE);
  675. if (!(ParseSequence (&tmpPtr, &msgLen))) // sequence
  676. return (FALSE);
  677. if (!(ParseUInt (&tmpPtr, &msgLen, &tmp))) // version
  678. return (FALSE);
  679. // Jump over communityString...not needed here
  680. if (ParseType (&tmpPtr, &msgLen) == -1)
  681. return (FALSE);
  682. // -1 is error, we also reject 0 and -ve length commuityString
  683. if ((tmp = ParseLength (&tmpPtr, &msgLen)) <= 0)
  684. return (FALSE);
  685. if ((smiUINT32)tmp > msgLen)
  686. return (FALSE);
  687. tmpPtr += (smiUINT32)tmp; // Jump!
  688. // Set the PDU type byte
  689. *tmpPtr = (smiBYTE)pduType;
  690. return (TRUE);
  691. } // End_SetPduType()
  692. smiUINT32 ParsePduHdr (smiLPBYTE msgPtr, smiUINT32 msgLen,
  693. smiLPUINT32 version, smiLPINT32 type, smiLPUINT32 reqID)
  694. {
  695. // This is a private function (not exported via WinSNMP)
  696. // It is called only once by msgNotify() (another private function)
  697. // to "peek ahead" at certain PDU attributes to determine the next
  698. // procesing steps.
  699. smiINT32 pduLen;
  700. smiINT32 length;
  701. long errcode = 1;
  702. if (msgPtr == NULL)
  703. goto DONE;
  704. errcode++; // 2
  705. // Parse initial Sequence field...
  706. if (ParseType (&msgPtr, &msgLen) != SNMP_SYNTAX_SEQUENCE)
  707. goto DONE;
  708. errcode++; // 3
  709. // ...to get the remaining pduLen out of it
  710. pduLen = ParseLength (&msgPtr, &msgLen);
  711. if (pduLen <= 0)
  712. goto DONE;
  713. errcode++; // 4
  714. if ((smiUINT32)pduLen > msgLen)
  715. goto DONE;
  716. errcode++; // 5
  717. msgLen = (smiUINT32)pduLen; // Only pduLen counts now
  718. if (!(ParseUInt (&msgPtr, &msgLen, version)))
  719. goto DONE;
  720. errcode++; // 6
  721. // Jump over communityString...not needed here
  722. if (ParseType (&msgPtr, &msgLen) == -1)
  723. goto DONE;
  724. errcode++; // 7
  725. // -1 is error, we also reject 0 and -ve length commuityString
  726. if ((length = ParseLength (&msgPtr, &msgLen)) <= 0)
  727. goto DONE;
  728. errcode++; // 8
  729. if ((smiUINT32)length > msgLen)
  730. goto DONE;
  731. errcode++; // 9
  732. msgPtr += (smiUINT32)length; // Jump!
  733. msgLen -= (smiUINT32)length;
  734. // Get PDU type
  735. if ((*type = ParseType (&msgPtr, &msgLen)) == -1)
  736. goto DONE;
  737. errcode++; // 10
  738. // Check PDU type for requestID semantics
  739. if (*type == SNMP_PDU_V1TRAP)
  740. *reqID = 0; // No requestID on v1 trapPDU
  741. else // Not a v1 trapPDU, therefore
  742. { // must get requestID
  743. // -1 is error, reject 0 and any -ve values too.
  744. if ((ParseLength (&msgPtr, &msgLen)) <= 0)
  745. goto DONE;
  746. errcode++; // 11
  747. if (!(ParseInt (&msgPtr, &msgLen, reqID)))
  748. goto DONE;
  749. }
  750. errcode = 0;
  751. DONE:
  752. return (errcode);
  753. } // end_ParsePduHdr
  754. smiUINT32 ParseMessage (smiLPBYTE msgPtr, smiUINT32 msgLen,
  755. smiLPUINT32 version, smiLPOCTETS *community, LPPDUS pdu)
  756. {
  757. smiINT32 pduLen;
  758. smiLPOCTETS os_ptr;
  759. LPVARBIND vb_ptr;
  760. LPVARBIND vb_end_ptr;
  761. long errcode = 1;
  762. if (msgPtr == NULL)
  763. goto DONE;
  764. errcode++; // 2
  765. // Parse initial Sequence field...
  766. if (ParseType (&msgPtr, &msgLen) != SNMP_SYNTAX_SEQUENCE)
  767. goto DONE;
  768. errcode++; // 3
  769. // ...to get the remaining pduLen out of it
  770. pduLen = ParseLength (&msgPtr, &msgLen);
  771. if (pduLen <= 0)
  772. goto DONE;
  773. errcode++; // 4
  774. if ((smiUINT32)pduLen > msgLen)
  775. goto DONE;
  776. errcode++; // 5
  777. msgLen = (smiUINT32)pduLen; // Only pduLen counts now
  778. if (!(ParseUInt (&msgPtr, &msgLen, version)))
  779. goto DONE;
  780. errcode++; // 5
  781. if (*version != 0 && *version != 1) // SNMPv1 or SNMPv2c
  782. goto DONE;
  783. errcode++; // 6
  784. if (!(os_ptr = GlobalAlloc (GPTR, sizeof(smiOCTETS))))
  785. goto DONE;
  786. errcode++; // 7
  787. if (!(ParseOctetString (&msgPtr, &msgLen, os_ptr)))
  788. goto DONE_OS;
  789. // reject 0 length community string
  790. if (os_ptr->len == 0)
  791. goto DONE_OS;
  792. errcode++; // 8
  793. if (pdu == NULL)
  794. goto DONE_OS;
  795. ZeroMemory (pdu, sizeof(PDUS));
  796. if ((pdu->type = ParseType (&msgPtr, &msgLen)) == -1)
  797. goto DONE_PDU;
  798. errcode++; // 9
  799. pduLen = ParseLength (&msgPtr, &msgLen);
  800. if ((pduLen <= 0) || (smiUINT32)pduLen > msgLen)
  801. goto DONE_PDU;
  802. errcode++; // 10
  803. switch (pdu->type)
  804. {
  805. case SNMP_PDU_GET:
  806. case SNMP_PDU_GETNEXT:
  807. case SNMP_PDU_RESPONSE:
  808. case SNMP_PDU_SET:
  809. case SNMP_PDU_GETBULK:
  810. case SNMP_PDU_INFORM:
  811. case SNMP_PDU_TRAP:
  812. if (!(ParseInt (&msgPtr, &msgLen, &pdu->appReqId)))
  813. goto DONE_PDU;
  814. errcode++; // 11
  815. if (!(ParseInt (&msgPtr, &msgLen, &pdu->errStatus)))
  816. goto DONE_PDU;
  817. errcode++; // 12
  818. if (!(ParseInt (&msgPtr, &msgLen, &pdu->errIndex)))
  819. goto DONE_PDU;
  820. errcode++; // 13
  821. break;
  822. case SNMP_PDU_V1TRAP:
  823. pdu->v1Trap = GlobalAlloc (GPTR, sizeof(V1TRAP));
  824. if (pdu->v1Trap == NULL)
  825. goto DONE_PDU;
  826. errcode++; // 11
  827. if (!(ParseOID (&msgPtr, &msgLen, &pdu->v1Trap->enterprise)))
  828. goto DONE_PDU;
  829. errcode++; // 12
  830. if (!(ParseOctetString (&msgPtr, &msgLen, &pdu->v1Trap->agent_addr)))
  831. goto DONE_PDU;
  832. errcode++; // 13
  833. if (!(ParseInt (&msgPtr, &msgLen, &pdu->v1Trap->generic_trap)))
  834. goto DONE_PDU;
  835. errcode++; // 14
  836. if (!(ParseInt (&msgPtr, &msgLen, &pdu->v1Trap->specific_trap)))
  837. goto DONE_PDU;
  838. errcode++; // 15
  839. if (!(ParseUInt (&msgPtr, &msgLen, &pdu->v1Trap->time_ticks)))
  840. goto DONE_PDU;
  841. errcode++; // 16
  842. break;
  843. default:
  844. goto DONE_PDU;
  845. } // end_switch
  846. errcode = 20; // re-normalize
  847. // Waste the SEQUENCE tag
  848. if (!(ParseSequence (&msgPtr, &msgLen)))
  849. goto DONE_PDU;
  850. errcode++; // 21
  851. // Parse the varbind list
  852. pdu->VBL = 0;
  853. pdu->VBL_addr = NULL;
  854. while (msgLen)
  855. {
  856. if (!(vb_ptr = ParseVarBind (&msgPtr, &msgLen)))
  857. goto DONE_PDU;
  858. errcode++; // 22+
  859. if (!pdu->VBL_addr) // Is this the first one?
  860. vb_end_ptr = pdu->VBL_addr = vb_ptr; // If so, start a list
  861. else
  862. { // tack onto end of list
  863. vb_end_ptr->next_var = vb_ptr;
  864. vb_end_ptr = vb_ptr;
  865. }
  866. } // end_while
  867. errcode = 0;
  868. *community = os_ptr;
  869. goto DONE;
  870. DONE_PDU:
  871. FreeVarBindList (pdu->VBL_addr); // Checks for NULL
  872. FreeV1Trap (pdu->v1Trap); // Checks for NULL
  873. ZeroMemory (pdu, sizeof(PDUS));
  874. DONE_OS:
  875. FreeOctetString (os_ptr);
  876. DONE:
  877. return (errcode);
  878. } // end_ParseMessage
  879. LPVARBIND ParseVarBind (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen)
  880. {
  881. LPVARBIND vb_ptr;
  882. if (!(ParseSequence (tmpPtr, tmpLen)))
  883. return (NULL);
  884. if ((vb_ptr = (LPVARBIND)GlobalAlloc(GPTR, sizeof(VARBIND))) == NULL)
  885. return (NULL);
  886. if (!(ParseOID(tmpPtr, tmpLen, &vb_ptr->name)))
  887. goto ERROROUT;
  888. //we're going to derefrence (*tmpPtr), check length left first
  889. if (*tmpLen == 0)
  890. goto ERROROUT;
  891. vb_ptr->value.syntax = (smiUINT32)*(*tmpPtr);
  892. switch (vb_ptr->value.syntax)
  893. {
  894. case SNMP_SYNTAX_CNTR32:
  895. case SNMP_SYNTAX_GAUGE32:
  896. case SNMP_SYNTAX_TIMETICKS:
  897. case SNMP_SYNTAX_UINT32:
  898. if (!(ParseUInt (tmpPtr, tmpLen, &vb_ptr->value.value.uNumber)))
  899. goto ERROROUT;
  900. break;
  901. case SNMP_SYNTAX_INT:
  902. if (!(ParseInt (tmpPtr, tmpLen, &vb_ptr->value.value.sNumber)))
  903. goto ERROROUT;
  904. break;
  905. case SNMP_SYNTAX_OID:
  906. if (!(ParseOID (tmpPtr, tmpLen, &vb_ptr->value.value.oid)))
  907. goto ERROROUT;
  908. break;
  909. case SNMP_SYNTAX_CNTR64:
  910. if (!(ParseCntr64 (tmpPtr, tmpLen, &vb_ptr->value.value.hNumber)))
  911. goto ERROROUT;
  912. break;
  913. case SNMP_SYNTAX_OCTETS:
  914. case SNMP_SYNTAX_IPADDR:
  915. case SNMP_SYNTAX_OPAQUE:
  916. if (!(ParseOctetString (tmpPtr, tmpLen, &vb_ptr->value.value.string)))
  917. goto ERROROUT;
  918. break;
  919. case SNMP_SYNTAX_NULL:
  920. case SNMP_SYNTAX_NOSUCHOBJECT:
  921. case SNMP_SYNTAX_NOSUCHINSTANCE:
  922. case SNMP_SYNTAX_ENDOFMIBVIEW:
  923. if (!(ParseNull (tmpPtr, tmpLen)))
  924. goto ERROROUT;
  925. break;
  926. default:
  927. goto ERROROUT;
  928. } // end_switch
  929. return (vb_ptr); // Success
  930. //
  931. ERROROUT:
  932. FreeVarBind(vb_ptr);
  933. return (NULL); // Failure
  934. } // end_ParseVarBind
  935. BOOL ParseOctetString
  936. (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen, smiLPOCTETS os_ptr)
  937. {
  938. smiINT32 length;
  939. if (!os_ptr)
  940. return (FALSE);
  941. os_ptr->ptr = NULL;
  942. os_ptr->len = 0;
  943. if (ParseType (tmpPtr, tmpLen) == -1)
  944. return (FALSE);
  945. // make sure no conversion to UINT is done before testing
  946. // because os_ptr->len is of UINT type
  947. length = ParseLength (tmpPtr, tmpLen);
  948. // note: we don't reject zero length Octet String
  949. if (length < 0 || (smiUINT32)length > *tmpLen)
  950. return (FALSE);
  951. os_ptr->len = (smiUINT32)length;
  952. if (os_ptr->len)
  953. { // Does not allocate "string" space on "length = 0"
  954. if (!(os_ptr->ptr = (smiLPBYTE)GlobalAlloc (GPTR, os_ptr->len)))
  955. return (FALSE);
  956. CopyMemory (os_ptr->ptr, *tmpPtr, os_ptr->len);
  957. }
  958. *tmpPtr += os_ptr->len;
  959. *tmpLen -= os_ptr->len;
  960. return (TRUE);
  961. } // end_ParseOctetString
  962. BOOL ParseOID (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen, smiLPOID oid_ptr)
  963. {
  964. smiINT32 length;
  965. if (!oid_ptr)
  966. return (FALSE);
  967. oid_ptr->ptr = NULL;
  968. oid_ptr->len = 0;
  969. if (ParseType (tmpPtr, tmpLen) != SNMP_SYNTAX_OID)
  970. return (FALSE);
  971. length = ParseLength (tmpPtr, tmpLen);
  972. // -1 is error return from ParseLength()
  973. // BUG# 347175 this is just the length in bytes for the BER encoded OID in the stream,
  974. // this code should be the same as in %sdxroot%\net\snmp\newagent\exe\snmppdus.c!ParseOid.
  975. // removed the (|| length > MAXOBJIDSIZE) condition from the following test. It should be
  976. // moved to the while loop to test the number of sub-ids instead of bytes in stream.
  977. if (length <= 0)
  978. return (FALSE);
  979. if ((smiUINT32)length > *tmpLen)
  980. return (FALSE);
  981. // the sub-id array will by 1 longer than the ASN.1/BER array
  982. oid_ptr->ptr = (smiLPUINT32)GlobalAlloc (GPTR, sizeof(smiUINT32) * (length+1));
  983. if (oid_ptr->ptr == NULL)
  984. return (FALSE);
  985. // oid_ptr structure space is pre-zero'd via GlobalAlloc()
  986. while (length && (oid_ptr->len < MAXOBJIDSIZE))
  987. {
  988. if (oid_ptr->ptr[oid_ptr->len] & 0xFE000000)
  989. {
  990. // overflow in the next left shift
  991. GlobalFree(oid_ptr->ptr);
  992. oid_ptr->ptr = NULL;
  993. oid_ptr->len = 0;
  994. return (FALSE);
  995. }
  996. oid_ptr->ptr[oid_ptr->len] =
  997. (oid_ptr->ptr[oid_ptr->len] << 7) + (*(*tmpPtr) & 0x7F);
  998. if ((*(*tmpPtr)++ & 0x80) == 0)
  999. { // on the last octet of this sub-id
  1000. if (oid_ptr->len == 0) // check for first sub-id
  1001. { // ASN.1/BER packs two into it
  1002. oid_ptr->ptr[1] = oid_ptr->ptr[0];
  1003. oid_ptr->ptr[0] /= 40;
  1004. if (oid_ptr->ptr[0] > 2)
  1005. oid_ptr->ptr[0] = 2;
  1006. oid_ptr->ptr[1] -= (oid_ptr->ptr[0] * 40);
  1007. oid_ptr->len++; // extra bump
  1008. }
  1009. oid_ptr->len++; // increment the count on sub-id
  1010. }
  1011. length--;
  1012. (*tmpLen)--;
  1013. } // end_while (length)
  1014. // BUG 506192
  1015. // Invalid OID BER of the form like "06 07 FF FF FF FF FF FF FF"
  1016. // causes oid_ptr->len becomes 0. Each subidentifier should be
  1017. // encoded as a non-negative integer using as few 7-bit blocks as possible.
  1018. // The blocks are packed in octets with the first bit of each octet equal
  1019. // to 1 except for the last octet of each subidentifier. The example above
  1020. // does not have the last octet. Added the (0 == oid_ptr->len) test below.
  1021. if (length || (0 == oid_ptr->len))
  1022. {
  1023. // the above while loop is terminated without finishing the parsing of the stream
  1024. GlobalFree(oid_ptr->ptr);
  1025. oid_ptr->ptr = NULL;
  1026. oid_ptr->len = 0;
  1027. return (FALSE);
  1028. }
  1029. return (TRUE);
  1030. } // end_ParseOID
  1031. BOOL ParseCntr64 (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen, smiLPCNTR64 Cntr64_ptr)
  1032. {
  1033. smiINT32 i;
  1034. smiINT32 length;
  1035. if (ParseType (tmpPtr, tmpLen) != SNMP_SYNTAX_CNTR64)
  1036. return (FALSE);
  1037. length = ParseLength(tmpPtr, tmpLen);
  1038. if (length <= 0)
  1039. return (FALSE);
  1040. if ((smiUINT32)length > *tmpLen || length > 9 ||
  1041. (length == 9 && *(*tmpPtr) != 0x00))
  1042. return (FALSE);
  1043. while (length && *(*tmpPtr) == 0x00)
  1044. { // leading null octet?
  1045. (*tmpPtr)++; // if so, skip it
  1046. length--; // and don't count it
  1047. (*tmpLen)--; // Adjust remaining msg length
  1048. }
  1049. Cntr64_ptr->hipart = Cntr64_ptr->lopart = 0;
  1050. for (i = 0; i < length; i++)
  1051. {
  1052. Cntr64_ptr->hipart = (Cntr64_ptr->hipart << 8) +
  1053. (Cntr64_ptr->lopart >> 24);
  1054. Cntr64_ptr->lopart = (Cntr64_ptr->lopart << 8) +
  1055. (smiUINT32) *(*tmpPtr)++;
  1056. }
  1057. *tmpLen -= length;
  1058. return (TRUE);
  1059. } // end_ParseCntr64
  1060. BOOL ParseUInt (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen, smiLPUINT32 value)
  1061. {
  1062. smiINT32 length;
  1063. smiINT32 i;
  1064. if (ParseType (tmpPtr, tmpLen) == -1)
  1065. return (FALSE);
  1066. length = ParseLength(tmpPtr, tmpLen);
  1067. if (length <= 0)
  1068. return (FALSE);
  1069. if ((smiUINT32)length > *tmpLen)
  1070. return (FALSE);
  1071. if ((length > 5) || ((length > 4) && (*(*tmpPtr) != 0x00)))
  1072. return (FALSE);
  1073. while (length && *(*tmpPtr) == 0x00)
  1074. { // leading null octet?
  1075. (*tmpPtr)++; // if so, skip it
  1076. length--; // and don't count it
  1077. (*tmpLen)--; // Adjust remaining msg length
  1078. }
  1079. *value = 0;
  1080. for (i = 0; i < length; i++)
  1081. *value = (*value << 8) + (smiUINT32)*(*tmpPtr)++;
  1082. *tmpLen -= length;
  1083. return (TRUE);
  1084. } // end_ParseUInt()
  1085. BOOL ParseInt (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen, smiLPINT value)
  1086. {
  1087. smiINT32 length;
  1088. smiINT32 i;
  1089. smiINT32 sign;
  1090. if (ParseType (tmpPtr, tmpLen) != SNMP_SYNTAX_INT)
  1091. return (FALSE);
  1092. length = ParseLength (tmpPtr, tmpLen);
  1093. if (length <= 0)
  1094. return (FALSE);
  1095. if ((smiUINT32)length > *tmpLen || length > 4)
  1096. return (FALSE);
  1097. sign = ((*(*tmpPtr) & 0x80) == 0x00) ? 0x00 : 0xFF;
  1098. *value = 0;
  1099. for (i = 0; i < length; i++)
  1100. *value = (*value << 8) + (smiUINT32) *(*tmpPtr)++;
  1101. // sign-extend upper bits
  1102. for (i = length; i < 4; i++)
  1103. *value = *value + (sign << i * 8);
  1104. *tmpLen -= length;
  1105. return (TRUE);
  1106. } // end_ParseInt()
  1107. BOOL ParseNull (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen)
  1108. {
  1109. smiINT32 length;
  1110. if (ParseType (tmpPtr, tmpLen) == -1)
  1111. return (FALSE);
  1112. length = ParseLength (tmpPtr, tmpLen);
  1113. if (length != 0) // NULLs have no length
  1114. return (FALSE);
  1115. return (TRUE);
  1116. } // end_ParseNull
  1117. BOOL ParseSequence (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen)
  1118. {
  1119. if (ParseType (tmpPtr, tmpLen) != SNMP_SYNTAX_SEQUENCE)
  1120. return (FALSE);
  1121. if (ParseLength (tmpPtr, tmpLen) == -1)
  1122. return (FALSE);
  1123. return (TRUE);
  1124. } // end_ParseSequence
  1125. smiINT32 ParseType (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen)
  1126. {
  1127. // 980421 - BobN
  1128. // - replaced tmpLen logic with working_len logic
  1129. // - working_len is always checked on entry into a
  1130. // - Parse<xxx> function
  1131. smiINT32 type;
  1132. if (*tmpLen == 0)
  1133. return (-1);
  1134. type = *(*tmpPtr)++;
  1135. (*tmpLen)--; // Adjust remaining msg length
  1136. switch (type)
  1137. {
  1138. case SNMP_SYNTAX_INT:
  1139. case SNMP_SYNTAX_OCTETS:
  1140. case SNMP_SYNTAX_OID:
  1141. case SNMP_SYNTAX_SEQUENCE:
  1142. case SNMP_SYNTAX_IPADDR:
  1143. case SNMP_SYNTAX_CNTR32:
  1144. case SNMP_SYNTAX_GAUGE32:
  1145. case SNMP_SYNTAX_TIMETICKS:
  1146. case SNMP_SYNTAX_OPAQUE:
  1147. case SNMP_SYNTAX_UINT32:
  1148. case SNMP_SYNTAX_CNTR64:
  1149. case SNMP_SYNTAX_NULL:
  1150. case SNMP_SYNTAX_NOSUCHOBJECT:
  1151. case SNMP_SYNTAX_NOSUCHINSTANCE:
  1152. case SNMP_SYNTAX_ENDOFMIBVIEW:
  1153. case SNMP_PDU_GET:
  1154. case SNMP_PDU_GETNEXT:
  1155. case SNMP_PDU_RESPONSE:
  1156. case SNMP_PDU_SET:
  1157. case SNMP_PDU_V1TRAP:
  1158. case SNMP_PDU_GETBULK:
  1159. case SNMP_PDU_INFORM:
  1160. case SNMP_PDU_TRAP:
  1161. break;
  1162. default:
  1163. type = -1;
  1164. break;
  1165. }
  1166. return (type);
  1167. } // end_ParseType
  1168. smiINT32 ParseLength (smiLPBYTE *tmpPtr, smiLPUINT32 tmpLen)
  1169. {
  1170. // 980421 - BobN
  1171. // - replaced end_ptr logic with tmpLen logic
  1172. // - tmpLen is always checked on entry into a Parse<xxx>
  1173. // - function and is decremented as used therein.
  1174. smiINT32 length;
  1175. smiINT32 lenlen;
  1176. if (*tmpLen == 0)
  1177. return (-1);
  1178. length = (smiINT32) *(*tmpPtr)++;
  1179. (*tmpLen)--; // Adjust remaining msg length
  1180. // Check for short-form value
  1181. if (length < 0x80)
  1182. return (length);
  1183. // Long form
  1184. lenlen = length & 0x7F;
  1185. if ((smiUINT32)lenlen > *tmpLen || lenlen > 4 || lenlen < 1)
  1186. return (-1); // Out of bounds
  1187. *tmpLen -= lenlen; // Adjust remaining msg length
  1188. length = 0;
  1189. while (lenlen)
  1190. {
  1191. length = (length << 8) + *(*tmpPtr)++;
  1192. lenlen--;
  1193. }
  1194. return (length);
  1195. } // end_ParseLength