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.

659 lines
17 KiB

  1. // wsnmp_ut.c
  2. //
  3. // WinSNMP Utility 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 - BobN
  10. // - Mods to SnmpStrToIpxAddress() to permit '.' char
  11. // - as netnum/nodenum separator
  12. // 970310 - Removed extraneous functions
  13. //
  14. #include "winsnmp.inc"
  15. SNMPAPI_STATUS SNMPAPI_CALL
  16. SnmpGetLastError (IN HSNMP_SESSION hSession)
  17. {
  18. DWORD nSes;
  19. if (TaskData.hTask == 0)
  20. return (SNMPAPI_NOT_INITIALIZED);
  21. nSes = HandleToUlong(hSession) - 1;
  22. if (snmpValidTableEntry(&SessDescr, nSes))
  23. {
  24. LPSESSION pSession = snmpGetTableEntry(&SessDescr, nSes);
  25. return pSession->nLastError;
  26. }
  27. else
  28. return (TaskData.nLastError);
  29. } // end_SnmpGetLastError
  30. SNMPAPI_STATUS SNMPAPI_CALL
  31. SnmpStrToOid (IN LPCSTR string,
  32. OUT smiLPOID dstOID)
  33. {
  34. smiUINT32 i;
  35. smiUINT32 compIdx;
  36. SNMPAPI_STATUS lError;
  37. CHAR c;
  38. LPSTR pSep;
  39. // Must be initialized
  40. if (TaskData.hTask == 0)
  41. {
  42. lError = SNMPAPI_NOT_INITIALIZED;
  43. goto ERROR_OUT;
  44. }
  45. // use __try, __except to figure out if 'string' is a
  46. // valid pointer. We cannot use IsBadReadPtr() here, as far as
  47. // we have no idea for how many octets we should look.
  48. __try
  49. {
  50. smiUINT32 sLen;
  51. sLen = strlen(string);
  52. if (sLen == 0 || sLen >= MAXOBJIDSTRSIZE)
  53. {
  54. lError = SNMPAPI_OID_INVALID;
  55. goto ERROR_OUT;
  56. }
  57. }
  58. __except(EXCEPTION_EXECUTE_HANDLER)
  59. {
  60. lError = SNMPAPI_ALLOC_ERROR;
  61. goto ERROR_OUT;
  62. }
  63. // see if the dstOID pointer provided by the caller points to
  64. // a valid memory range. If null is provided, there is nothing
  65. // the API was requested to do!
  66. if (IsBadWritePtr (dstOID, sizeof(smiOID)))
  67. {
  68. lError = (dstOID == NULL) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR;
  69. goto ERROR_OUT;
  70. }
  71. // Ignore initial '.' in string (UNIX-ism)
  72. if (string[0] == '.')
  73. string++;
  74. // figure out how many components this OID has
  75. // count the number of '.' in the string. The OID should
  76. // contain this count + 1 components
  77. dstOID->len = 0;
  78. pSep = (LPSTR)string;
  79. while((pSep = strchr(pSep, '.')) != NULL)
  80. {
  81. pSep++;
  82. dstOID->len++;
  83. }
  84. dstOID->len++;
  85. // don't allow less than 2 components
  86. if (dstOID->len < 2)
  87. {
  88. lError = SNMPAPI_OID_INVALID;
  89. goto ERROR_OUT;
  90. }
  91. // allocate memory for holding the numeric OID components
  92. // this should be released by the caller, through 'SnmpFreeDescriptor()'
  93. dstOID->ptr = (smiLPUINT32)GlobalAlloc(GPTR, dstOID->len * sizeof(smiUINT32));
  94. if (dstOID->ptr == NULL)
  95. {
  96. lError = SNMPAPI_ALLOC_ERROR;
  97. goto ERROR_OUT;
  98. }
  99. compIdx = 0;
  100. // when entering the loop, 'string' doesn't have a heading '.'
  101. // NOTE: 123. will be accepted as 123.0
  102. // (123.. a12.3.4 1234....5.6) are considered as invalid OIDs instead
  103. // of truncated to (123.0 0 1234.0).
  104. while (*string != '\0')
  105. {
  106. dstOID->ptr[compIdx++] = strtoul(string, &pSep, 10);
  107. // if one of the components was overflowing, release the memory and bail out.
  108. if (errno == ERANGE)
  109. {
  110. errno = 0;
  111. lError = SNMPAPI_OID_INVALID;
  112. GlobalFree(dstOID->ptr);
  113. dstOID->ptr = NULL;
  114. goto ERROR_OUT;
  115. }
  116. // if strtoul did not make any progress on the string (two successive dots)
  117. // or it was blocked on something else than a separator or null-termination, then
  118. // there was an error. The OID is invalid. API return failure
  119. if (pSep == string ||
  120. (*pSep != '.' && *pSep != '\0'))
  121. {
  122. lError = SNMPAPI_OID_INVALID; // invalid char in sequence
  123. if (GlobalFree (dstOID->ptr)) // returns not-NULL on error
  124. {
  125. lError = SNMPAPI_OTHER_ERROR;
  126. goto ERROR_OUT;
  127. }
  128. dstOID->ptr = NULL;
  129. dstOID->len = 0;
  130. goto ERROR_OUT;
  131. }
  132. // pSep can point only to '.' or '\0'
  133. if (*pSep == '.')
  134. pSep++;
  135. // restart with string from this point
  136. string = pSep;
  137. }
  138. if (dstOID->len < 2)
  139. {
  140. GlobalFree(dstOID->ptr);
  141. dstOID->ptr = NULL;
  142. lError = SNMPAPI_OID_INVALID;
  143. goto ERROR_OUT;
  144. }
  145. return dstOID->len;
  146. ERROR_OUT:
  147. return (SaveError (0, lError));
  148. } // end_SnmpStrToOid()
  149. SNMPAPI_STATUS SNMPAPI_CALL
  150. SnmpOidToStr (IN smiLPCOID srcOID,
  151. IN smiUINT32 strLen,
  152. OUT LPSTR strPtr)
  153. {
  154. SNMPAPI_STATUS lError;
  155. smiUINT32 retLen = 0; // used for successful return
  156. smiUINT32 oidIdx = 0; // max subids is 128
  157. smiUINT32 tmpLen; // used for size of decoded string (with '.')
  158. LPSTR tmpPtr = strPtr; // used for advancing strPtr
  159. char tmpBuf[64]; // enough room for 1 32-bit decode and '.'
  160. if (TaskData.hTask == 0)
  161. {
  162. lError = SNMPAPI_NOT_INITIALIZED;
  163. goto ERROR_OUT;
  164. }
  165. if (!strLen)
  166. {
  167. lError = SNMPAPI_SIZE_INVALID;
  168. goto ERROR_OUT;
  169. }
  170. if (IsBadReadPtr(srcOID, sizeof(smiOID)) ||
  171. IsBadWritePtr(strPtr, strLen))
  172. {
  173. lError = (strPtr == NULL) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR;
  174. goto ERROR_OUT;
  175. }
  176. if (srcOID->len == 0 || srcOID->len > 128 ||
  177. IsBadReadPtr (srcOID->ptr, srcOID->len * sizeof(smiUINT32)))
  178. {
  179. lError = SNMPAPI_OID_INVALID;
  180. goto ERROR_OUT;
  181. }
  182. while (oidIdx < srcOID->len)
  183. {
  184. _ultoa (srcOID->ptr[oidIdx++], tmpBuf, 10);
  185. lstrcat (tmpBuf, ".");
  186. tmpLen = lstrlen (tmpBuf);
  187. if (strLen < (tmpLen + 1))
  188. {
  189. tmpBuf[strLen] = '\0';
  190. lstrcpy (tmpPtr, tmpBuf);
  191. lError = SNMPAPI_OUTPUT_TRUNCATED;
  192. goto ERROR_OUT;
  193. }
  194. lstrcpy (tmpPtr, tmpBuf);
  195. strLen -= tmpLen;
  196. tmpPtr += tmpLen;
  197. retLen += tmpLen;
  198. } // end_while
  199. *(--tmpPtr) = '\0';
  200. return (retLen);
  201. //
  202. ERROR_OUT:
  203. return (SaveError (0, lError));
  204. } // end_SnmpOidToStr
  205. SNMPAPI_STATUS SNMPAPI_CALL
  206. SnmpOidCopy (IN smiLPCOID srcOID,
  207. OUT smiLPOID dstOID)
  208. {
  209. SNMPAPI_STATUS lError;
  210. if (TaskData.hTask == 0)
  211. {
  212. lError = SNMPAPI_NOT_INITIALIZED;
  213. goto ERROR_OUT;
  214. }
  215. if (IsBadReadPtr (srcOID, sizeof(smiOID)) ||
  216. IsBadReadPtr (srcOID->ptr, srcOID->len) ||
  217. IsBadWritePtr (dstOID, sizeof(smiOID)))
  218. {
  219. lError = (dstOID == NULL) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR;
  220. goto ERROR_OUT;
  221. }
  222. // Check input OID size
  223. if ((srcOID->len == 0) ||(srcOID->len > MAXOBJIDSIZE))
  224. {
  225. lError = SNMPAPI_OID_INVALID;
  226. goto ERROR_OUT;
  227. }
  228. // Using dstOID-> temporarily for byte count
  229. dstOID->len = srcOID->len * sizeof(smiUINT32);
  230. // App must free following alloc via SnmpFreeDescriptor()
  231. if (!(dstOID->ptr = (smiLPUINT32)GlobalAlloc (GPTR, dstOID->len)))
  232. {
  233. lError = SNMPAPI_ALLOC_ERROR;
  234. goto ERROR_OUT;
  235. }
  236. CopyMemory (dstOID->ptr, srcOID->ptr, dstOID->len);
  237. // Now make dstOID->len mean the right thing
  238. dstOID->len = srcOID->len;
  239. return (dstOID->len);
  240. //
  241. ERROR_OUT:
  242. return (SaveError (0, lError));
  243. } // end_SnmpOidCopy()
  244. SNMPAPI_STATUS SNMPAPI_CALL
  245. SnmpFreeDescriptor (IN smiUINT32 syntax,
  246. IN smiLPOPAQUE ptr)
  247. {
  248. SNMPAPI_STATUS lError;
  249. if (TaskData.hTask == 0)
  250. {
  251. lError = SNMPAPI_NOT_INITIALIZED;
  252. goto ERROR_OUT;
  253. }
  254. if (!syntax || !ptr || !ptr->ptr)
  255. {
  256. lError = SNMPAPI_OPERATION_INVALID;
  257. goto ERROR_OUT;
  258. }
  259. switch (syntax)
  260. {
  261. case SNMP_SYNTAX_OCTETS:
  262. case SNMP_SYNTAX_IPADDR:
  263. case SNMP_SYNTAX_OPAQUE:
  264. case SNMP_SYNTAX_OID:
  265. if (GlobalFree (ptr->ptr)) // returns not-NULL on error
  266. {
  267. lError = SNMPAPI_OTHER_ERROR;
  268. goto ERROR_OUT;
  269. }
  270. ptr->ptr = NULL;
  271. ptr->len = 0;
  272. break;
  273. default:
  274. lError = SNMPAPI_SYNTAX_INVALID;
  275. goto ERROR_OUT;
  276. } // end_switch
  277. return (SNMPAPI_SUCCESS);
  278. //
  279. ERROR_OUT:
  280. return (SaveError (0, lError));
  281. } // end_SnmpFreeDescriptor
  282. // SnmpOidCompare
  283. //
  284. // Re-worked by 3/17/95 BobN
  285. SNMPAPI_STATUS SNMPAPI_CALL
  286. SnmpOidCompare (IN smiLPCOID xOID,
  287. IN smiLPCOID yOID,
  288. IN smiUINT32 maxlen,
  289. OUT smiLPINT result)
  290. {
  291. smiUINT32 i = 0;
  292. smiUINT32 j = 0;
  293. SNMPAPI_STATUS lError;
  294. if (TaskData.hTask == 0)
  295. {
  296. lError = SNMPAPI_NOT_INITIALIZED;
  297. goto ERROR_OUT;
  298. }
  299. if (maxlen > MAXOBJIDSIZE)
  300. {
  301. lError = SNMPAPI_SIZE_INVALID;
  302. goto ERROR_OUT;
  303. }
  304. if (IsBadReadPtr (xOID, sizeof(smiOID)) ||
  305. IsBadReadPtr (yOID, sizeof(smiOID)))
  306. {
  307. lError = SNMPAPI_ALLOC_ERROR;
  308. goto ERROR_OUT;
  309. }
  310. if (IsBadReadPtr (xOID->ptr, xOID->len * sizeof(UINT)) ||
  311. IsBadReadPtr (yOID->ptr, yOID->len * sizeof(UINT)))
  312. {
  313. lError = SNMPAPI_OID_INVALID;
  314. goto ERROR_OUT;
  315. }
  316. // Test input pointers for readability
  317. if (IsBadWritePtr (result, sizeof(smiINT)))
  318. {
  319. lError = (result == NULL) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR;
  320. goto ERROR_OUT;
  321. }
  322. j = min(xOID->len, yOID->len);
  323. if (maxlen) j = min(j, maxlen);
  324. while (i < j)
  325. {
  326. if (*result = xOID->ptr[i] - yOID->ptr[i]) // deliberate assignment
  327. return (SNMPAPI_SUCCESS); // not equal...got a winner!
  328. i++;
  329. }
  330. if (j == maxlen) // asked for a limit
  331. return (SNMPAPI_SUCCESS); // and...got a draw!
  332. *result = xOID->len - yOID->len; // size matters!
  333. return SNMPAPI_SUCCESS;
  334. //
  335. ERROR_OUT:
  336. return (SaveError (0, lError));
  337. } // end_SnmpOidCompare
  338. SNMPAPI_STATUS SNMPAPI_CALL
  339. SnmpEncodeMsg (IN HSNMP_SESSION hSession,
  340. IN HSNMP_ENTITY hSrc,
  341. IN HSNMP_ENTITY hDst,
  342. IN HSNMP_CONTEXT hCtx,
  343. IN HSNMP_PDU hPdu,
  344. IN OUT smiLPOCTETS msgBufDesc)
  345. {
  346. smiUINT32 version = 0;
  347. DWORD nCtx;
  348. DWORD nPdu;
  349. DWORD nVbl;
  350. smiOCTETS tmpContext;
  351. smiLPBYTE msgAddr = NULL;
  352. smiUINT32 lError = SNMPAPI_SUCCESS;
  353. HSNMP_SESSION lSession = 0;
  354. LPPDUS pPdu;
  355. LPENTITY pEntSrc, pEntDst;
  356. LPCTXT pCtxt;
  357. // Basic error checks
  358. if (TaskData.hTask == 0)
  359. {
  360. lError = SNMPAPI_NOT_INITIALIZED;
  361. goto ERROR_OUT;
  362. }
  363. if (!snmpValidTableEntry(&SessDescr, HandleToUlong(hSession)-1))
  364. {
  365. lError = SNMPAPI_SESSION_INVALID;
  366. goto ERROR_OUT;
  367. }
  368. // We have a valid session at this point...
  369. lSession = hSession; // save it for possible error return
  370. // Check for writable output buffer
  371. if (IsBadWritePtr (msgBufDesc, sizeof(smiOCTETS)))
  372. {
  373. lError = (msgBufDesc == NULL) ? SNMPAPI_NOOP : SNMPAPI_ALLOC_ERROR;
  374. goto ERROR_OUT;
  375. }
  376. // srcEntity not currently used
  377. if (hSrc)
  378. {
  379. if (!snmpValidTableEntry(&EntsDescr, HandleToUlong(hSrc)-1))
  380. {
  381. lError = SNMPAPI_ENTITY_INVALID;
  382. goto ERROR_OUT;
  383. }
  384. pEntSrc = snmpGetTableEntry(&EntsDescr, HandleToUlong(hSrc)-1);
  385. }
  386. // dstEntity is required for *accurate* msg version info
  387. if (hDst)
  388. {
  389. if (!snmpValidTableEntry(&EntsDescr, HandleToUlong(hDst)-1))
  390. {
  391. lError = SNMPAPI_ENTITY_INVALID;
  392. goto ERROR_OUT;
  393. }
  394. pEntDst = snmpGetTableEntry(&EntsDescr, HandleToUlong(hDst)-1);
  395. version = pEntDst->version-1;
  396. }
  397. nCtx = HandleToUlong(hCtx) - 1;
  398. if (!snmpValidTableEntry(&CntxDescr, nCtx))
  399. {
  400. lError = SNMPAPI_CONTEXT_INVALID;
  401. goto ERROR_OUT;
  402. }
  403. pCtxt = snmpGetTableEntry(&CntxDescr, nCtx);
  404. nPdu = HandleToUlong(hPdu) - 1;
  405. if (!snmpValidTableEntry(&PDUsDescr, nPdu))
  406. {
  407. ERROR_PDU:
  408. lError = SNMPAPI_PDU_INVALID;
  409. goto ERROR_OUT;
  410. }
  411. pPdu = snmpGetTableEntry(&PDUsDescr, nPdu);
  412. // Necessary PDU data checks
  413. nVbl = HandleToUlong(pPdu->VBL);
  414. if (!snmpValidTableEntry(&VBLsDescr, nVbl-1))
  415. goto ERROR_PDU;
  416. // Check out for SNMPv1 Trap PDU type...uses different PDU structure!
  417. // ???
  418. // Check for SNMPv2c PDU types
  419. if (pPdu->type == SNMP_PDU_TRAP ||
  420. pPdu->type == SNMP_PDU_INFORM)
  421. version = 1;
  422. // Now Build it
  423. tmpContext.len = pCtxt->commLen;
  424. tmpContext.ptr = pCtxt->commStr;
  425. if (!(BuildMessage (version, &tmpContext,
  426. pPdu, pPdu->appReqId,
  427. &msgAddr, &msgBufDesc->len)))
  428. goto ERROR_PDU;
  429. // Copy Snmp message to caller's buffer...
  430. // App must free following alloc via SnmpFreeDescriptor()
  431. if (!(msgBufDesc->ptr = (smiLPBYTE)GlobalAlloc (GPTR, msgBufDesc->len)))
  432. lError = SNMPAPI_ALLOC_ERROR;
  433. else // SUCCESS
  434. CopyMemory (msgBufDesc->ptr, msgAddr, msgBufDesc->len);
  435. ERROR_OUT:
  436. // Clean up
  437. if (msgAddr)
  438. GlobalFree (msgAddr);
  439. if (lError == SNMPAPI_SUCCESS)
  440. return (msgBufDesc->len);
  441. else // Failure cases
  442. return (SaveError (lSession, lError));
  443. }
  444. SNMPAPI_STATUS SNMPAPI_CALL
  445. SnmpDecodeMsg (IN HSNMP_SESSION hSession,
  446. OUT LPHSNMP_ENTITY hSrc,
  447. OUT LPHSNMP_ENTITY hDst,
  448. OUT LPHSNMP_CONTEXT hCtx,
  449. OUT LPHSNMP_PDU hPdu,
  450. IN smiLPCOCTETS msgPtr)
  451. {
  452. DWORD nPdu;
  453. smiLPOCTETS community;
  454. smiUINT32 version;
  455. SNMPAPI_STATUS lError = SNMPAPI_SUCCESS;
  456. HSNMP_SESSION lSession = 0;
  457. LPPDUS pPdu;
  458. if (TaskData.hTask == 0)
  459. {
  460. lError = SNMPAPI_NOT_INITIALIZED;
  461. goto ERROR_OUT;
  462. }
  463. if (!snmpValidTableEntry(&SessDescr, HandleToUlong(hSession)-1))
  464. {
  465. lError = SNMPAPI_SESSION_INVALID;
  466. goto ERROR_OUT;
  467. }
  468. // Valid session...save for possible error return
  469. lSession = hSession;
  470. if (IsBadReadPtr(msgPtr, sizeof(smiOCTETS)) ||
  471. IsBadReadPtr(msgPtr->ptr, msgPtr->len))
  472. {
  473. lError = SNMPAPI_ALLOC_ERROR;
  474. goto ERROR_OUT;
  475. }
  476. if (hSrc == NULL && hDst == NULL && hCtx == NULL && hPdu == NULL)
  477. {
  478. lError = SNMPAPI_NOOP;
  479. goto ERROR_OUT;
  480. }
  481. if ((hDst != NULL && IsBadWritePtr(hDst, sizeof(HSNMP_ENTITY))) ||
  482. (hSrc != NULL && IsBadWritePtr(hSrc, sizeof(HSNMP_ENTITY))))
  483. {
  484. lError = SNMPAPI_ENTITY_INVALID;
  485. goto ERROR_OUT;
  486. }
  487. if (hCtx != NULL && IsBadWritePtr(hCtx, sizeof(HSNMP_CONTEXT)))
  488. {
  489. lError = SNMPAPI_CONTEXT_INVALID;
  490. goto ERROR_OUT;
  491. }
  492. if (IsBadWritePtr(hPdu, sizeof(HSNMP_PDU)))
  493. {
  494. lError = SNMPAPI_PDU_INVALID;
  495. goto ERROR_OUT;
  496. }
  497. EnterCriticalSection (&cs_PDU);
  498. lError = snmpAllocTableEntry(&PDUsDescr, &nPdu);
  499. if (lError != SNMPAPI_SUCCESS)
  500. goto ERROR_PRECHECK;
  501. pPdu = snmpGetTableEntry(&PDUsDescr, nPdu);
  502. if (ParseMessage (msgPtr->ptr, msgPtr->len, &version, &community, pPdu))
  503. { // non-zero = some error code
  504. lError = SNMPAPI_MESSAGE_INVALID;
  505. SnmpFreePdu((HSNMP_PDU) ULongToPtr(nPdu+1));
  506. goto ERROR_PRECHECK;
  507. }
  508. if (hDst != NULL) *hDst = 0;
  509. if (hSrc != NULL) *hSrc = 0;
  510. if (hCtx != NULL)
  511. {
  512. smiUINT32 nMode;
  513. EnterCriticalSection (&cs_XMODE);
  514. SnmpGetTranslateMode (&nMode);
  515. SnmpSetTranslateMode (SNMPAPI_UNTRANSLATED_V1);
  516. if ((*hCtx = SnmpStrToContext (hSession, community)) == SNMPAPI_FAILURE)
  517. {
  518. LeaveCriticalSection (&cs_XMODE);
  519. lError = SNMPAPI_OTHER_ERROR;
  520. FreeOctetString (community);
  521. SnmpFreePdu((HSNMP_PDU) ULongToPtr(nPdu+1));
  522. goto ERROR_PRECHECK;
  523. }
  524. SnmpSetTranslateMode (nMode);
  525. LeaveCriticalSection (&cs_XMODE);
  526. }
  527. FreeOctetString (community);
  528. pPdu->Session = hSession;
  529. if (hPdu != NULL)
  530. *hPdu = (HSNMP_PDU) ULongToPtr(nPdu+1);
  531. else
  532. SnmpFreePdu((HSNMP_PDU) ULongToPtr(nPdu+1));
  533. ERROR_PRECHECK:
  534. LeaveCriticalSection (&cs_PDU);
  535. if (lError == SNMPAPI_SUCCESS)
  536. {
  537. SaveError(lSession, lError);
  538. return (msgPtr->len);
  539. }
  540. ERROR_OUT:
  541. return (SaveError (lSession, lError));
  542. } // end_SnmpDecodeMsg()
  543. #define NETLEN 4
  544. #define NODELEN 6
  545. char *cHexDigits = "0123456789ABCDEF";
  546. SNMPAPI_STATUS SNMPAPI_CALL
  547. SnmpStrToIpxAddress (LPCSTR str, LPBYTE netnum, LPBYTE nodenum)
  548. {
  549. LPSTR netPtr, nodePtr, pStr;
  550. DWORD i, j;
  551. char tmpStr[24+1];
  552. BYTE c1, c2;
  553. if (!str || !netnum || !nodenum)
  554. return (SNMPAPI_FAILURE);
  555. strncpy (tmpStr, str,24);
  556. tmpStr[24] = '\0';
  557. netPtr = strtok (tmpStr, "-:.");
  558. if (netPtr == NULL)
  559. return (SNMPAPI_FAILURE);
  560. if (lstrlen (netPtr) != NETLEN*2)
  561. return (SNMPAPI_FAILURE);
  562. nodePtr = netPtr + (NETLEN*2) + 1;
  563. if (lstrlen (nodePtr) != NODELEN*2)
  564. return (SNMPAPI_FAILURE);
  565. _strupr (netPtr);
  566. for (i = 0, j = 0; j < NETLEN; j++)
  567. {
  568. pStr = strchr (cHexDigits, netPtr[i++]);
  569. if (pStr == NULL)
  570. return (SNMPAPI_FAILURE);
  571. c1 = (BYTE)(pStr - cHexDigits);
  572. pStr = strchr (cHexDigits, netPtr[i++]);
  573. if (pStr == NULL)
  574. return (SNMPAPI_FAILURE);
  575. c2 = (BYTE)(pStr - cHexDigits);
  576. netnum[j] = c2 | c1 << 4;
  577. }
  578. _strupr (nodePtr);
  579. for (i = 0, j = 0; j < NODELEN; j++)
  580. {
  581. pStr = strchr (cHexDigits, nodePtr[i++]);
  582. if (pStr == NULL)
  583. return (SNMPAPI_FAILURE);
  584. c1 = (BYTE)(pStr - cHexDigits);
  585. pStr = strchr (cHexDigits, nodePtr[i++]);
  586. if (pStr == NULL)
  587. return (SNMPAPI_FAILURE);
  588. c2 = (BYTE)(pStr - cHexDigits);
  589. nodenum[j] = c2 | c1 << 4;
  590. }
  591. return (SNMPAPI_SUCCESS);
  592. }
  593. SNMPAPI_STATUS SNMPAPI_CALL
  594. SnmpIpxAddressToStr (LPBYTE netnum, LPBYTE nodenum, LPSTR str)
  595. {
  596. DWORD i, j;
  597. for (i = 0, j = 0; i < NETLEN; i++)
  598. {
  599. str[j++] = cHexDigits[(netnum[i] & 0xF0) >> 4];
  600. str[j++] = cHexDigits[netnum[i] & 0x0F];
  601. }
  602. str[j++] = ':';
  603. for (i = 0; i < NODELEN; i++)
  604. {
  605. str[j++] = cHexDigits[(nodenum[i] & 0xF0) >> 4];
  606. str[j++] = cHexDigits[nodenum[i] & 0x0F];
  607. }
  608. str[j] = '\0';
  609. return (SNMPAPI_SUCCESS);
  610. }