Implemented SNMP table tools on server level
[public/netxms.git] / src / server / core / snmp.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003, 2004, 2005 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** $module: snmp.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25
26 //
27 // OID translation structure
28 //
29
30 struct OID_TABLE
31 {
32 TCHAR *pszOid;
33 DWORD dwNodeType;
34 DWORD dwNodeFlags;
35 };
36
37
38 //
39 // Static data
40 //
41
42 static OID_TABLE *m_pOidTable = NULL;
43 static DWORD m_dwOidTableSize = 0;
44 static DWORD m_dwRequestId = 1;
45
46
47 //
48 // Generate new request ID
49 //
50
51 DWORD SnmpNewRequestId(void)
52 {
53 return m_dwRequestId++;
54 }
55
56
57 //
58 // Initialize SNMP subsystem
59 //
60
61 void SnmpInit(void)
62 {
63 DB_RESULT hResult;
64 DWORD i;
65
66 // Load OID to type translation table
67 hResult = DBSelect(g_hCoreDB, _T("SELECT snmp_oid,node_type,node_flags FROM oid_to_type ORDER BY pair_id"));
68 if (hResult != NULL)
69 {
70 m_dwOidTableSize = DBGetNumRows(hResult);
71 m_pOidTable = (OID_TABLE *)malloc(sizeof(OID_TABLE) * m_dwOidTableSize);
72 for(i = 0; i < m_dwOidTableSize; i++)
73 {
74 m_pOidTable[i].pszOid = _tcsdup(DBGetField(hResult, i, 0));
75 m_pOidTable[i].dwNodeType = DBGetFieldULong(hResult, i, 1);
76 m_pOidTable[i].dwNodeFlags = DBGetFieldULong(hResult, i, 2);
77 }
78 DBFreeResult(hResult);
79 }
80 }
81
82
83 //
84 // Determine node type by OID
85 //
86
87 DWORD OidToType(TCHAR *pszOid, DWORD *pdwFlags)
88 {
89 DWORD i;
90
91 for(i = 0; i < m_dwOidTableSize; i++)
92 if (MatchString(m_pOidTable[i].pszOid, pszOid, TRUE))
93 {
94 if (pdwFlags != NULL)
95 *pdwFlags = m_pOidTable[i].dwNodeFlags;
96 return m_pOidTable[i].dwNodeType;
97 }
98
99 *pdwFlags = 0;
100 return NODE_TYPE_GENERIC;
101 }
102
103
104 //
105 // Get value for SNMP variable
106 // If szOidStr is not NULL, string representation of OID is used, otherwise -
107 // binary representation from oidBinary and dwOidLen
108 //
109
110 DWORD SnmpGet(DWORD dwVersion, DWORD dwAddr, WORD wPort, const char *szCommunity,
111 const char *szOidStr, const DWORD *oidBinary, DWORD dwOidLen, void *pValue,
112 DWORD dwBufferSize, BOOL bVerbose, BOOL bStringResult)
113 {
114 SNMP_Transport *pTransport;
115 SNMP_PDU *pRqPDU, *pRespPDU;
116 DWORD dwNameLen, pdwVarName[MAX_OID_LEN], dwResult;
117
118 // Open SNMP session
119 pTransport = new SNMP_Transport;
120 dwResult = pTransport->CreateUDPTransport(NULL, htonl(dwAddr), wPort);
121 if (dwResult != SNMP_ERR_SUCCESS)
122 {
123 WriteLog(MSG_SNMP_TRANSPORT_FAILED, EVENTLOG_ERROR_TYPE, NULL);
124 }
125 else
126 {
127 // Create PDU and send request
128 pRqPDU = new SNMP_PDU(SNMP_GET_REQUEST, (char *)szCommunity, m_dwRequestId++, dwVersion);
129 if (szOidStr != NULL)
130 {
131 dwNameLen = SNMPParseOID(szOidStr, pdwVarName, MAX_OID_LEN);
132 if (dwNameLen == 0)
133 {
134 WriteLog(MSG_OID_PARSE_ERROR, EVENTLOG_ERROR_TYPE, "s", szOidStr);
135 dwResult = SNMP_ERR_BAD_OID;
136 }
137 }
138 else
139 {
140 memcpy(pdwVarName, oidBinary, dwOidLen * sizeof(DWORD));
141 dwNameLen = dwOidLen;
142 }
143
144 if (dwResult == SNMP_ERR_SUCCESS) // Still no errors
145 {
146 pRqPDU->BindVariable(new SNMP_Variable(pdwVarName, dwNameLen));
147 dwResult = pTransport->DoRequest(pRqPDU, &pRespPDU, 1000, 3);
148
149 // Analyze response
150 if (dwResult == SNMP_ERR_SUCCESS)
151 {
152 if ((pRespPDU->GetNumVariables() > 0) &&
153 (pRespPDU->GetErrorCode() == SNMP_PDU_ERR_SUCCESS))
154 {
155 SNMP_Variable *pVar = pRespPDU->GetVariable(0);
156
157 if ((pVar->GetType() != ASN_NO_SUCH_OBJECT) &&
158 (pVar->GetType() != ASN_NO_SUCH_INSTANCE))
159 {
160 if (bStringResult)
161 {
162 pVar->GetValueAsString((TCHAR *)pValue, dwBufferSize);
163 }
164 else
165 {
166 switch(pVar->GetType())
167 {
168 case ASN_INTEGER:
169 case ASN_UINTEGER32:
170 case ASN_COUNTER32:
171 case ASN_GAUGE32:
172 case ASN_TIMETICKS:
173 *((long *)pValue) = pVar->GetValueAsInt();
174 break;
175 case ASN_IP_ADDR:
176 *((long *)pValue) = ntohl(pVar->GetValueAsUInt());
177 break;
178 case ASN_OCTET_STRING:
179 pVar->GetValueAsString((TCHAR *)pValue, dwBufferSize);
180 break;
181 case ASN_OBJECT_ID:
182 pVar->GetValueAsString((TCHAR *)pValue, dwBufferSize);
183 break;
184 default:
185 WriteLog(MSG_SNMP_UNKNOWN_TYPE, EVENTLOG_ERROR_TYPE, "x", pVar->GetType());
186 dwResult = SNMP_ERR_BAD_TYPE;
187 break;
188 }
189 }
190 }
191 else
192 {
193 dwResult = SNMP_ERR_NO_OBJECT;
194 }
195 }
196 else
197 {
198 if (pRespPDU->GetErrorCode() == SNMP_PDU_ERR_NO_SUCH_NAME)
199 dwResult = SNMP_ERR_NO_OBJECT;
200 else
201 dwResult = SNMP_ERR_AGENT;
202 }
203 delete pRespPDU;
204 }
205 else
206 {
207 if (bVerbose)
208 WriteLog(MSG_SNMP_GET_ERROR, EVENTLOG_ERROR_TYPE, "d", dwResult);
209 }
210 }
211
212 delete pRqPDU;
213 }
214
215 delete pTransport;
216 return dwResult;
217 }
218
219
220 //
221 // Enumerate multiple values by walking throgh MIB, starting at given root
222 //
223
224 DWORD SnmpEnumerate(DWORD dwVersion, DWORD dwAddr, WORD wPort, const char *szCommunity,
225 const char *szRootOid,
226 void (* pHandler)(DWORD, DWORD, WORD, const char *, SNMP_Variable *, SNMP_Transport *, void *),
227 void *pUserArg, BOOL bVerbose)
228 {
229 DWORD pdwRootName[MAX_OID_LEN], dwRootLen, pdwName[MAX_OID_LEN], dwNameLen, dwResult;
230 SNMP_PDU *pRqPDU, *pRespPDU;
231 SNMP_Transport *pTransport;
232 BOOL bRunning = TRUE;
233
234 // Open SNMP session
235 pTransport = new SNMP_Transport;
236 dwResult = pTransport->CreateUDPTransport(NULL, htonl(dwAddr), wPort);
237 if (dwResult != SNMP_ERR_SUCCESS)
238 {
239 WriteLog(MSG_SNMP_TRANSPORT_FAILED, EVENTLOG_ERROR_TYPE, NULL);
240 }
241 else
242 {
243 // Get root
244 dwRootLen = SNMPParseOID(szRootOid, pdwRootName, MAX_OID_LEN);
245 if (dwRootLen == 0)
246 {
247 WriteLog(MSG_OID_PARSE_ERROR, EVENTLOG_ERROR_TYPE, "s", szRootOid);
248 dwResult = SNMP_ERR_BAD_OID;
249 }
250 else
251 {
252 memcpy(pdwName, pdwRootName, dwRootLen * sizeof(DWORD));
253 dwNameLen = dwRootLen;
254
255 // Walk the MIB
256 while(bRunning)
257 {
258 pRqPDU = new SNMP_PDU(SNMP_GET_NEXT_REQUEST, (char *)szCommunity, m_dwRequestId++, dwVersion);
259 pRqPDU->BindVariable(new SNMP_Variable(pdwName, dwNameLen));
260 dwResult = pTransport->DoRequest(pRqPDU, &pRespPDU, 1000, 3);
261
262 // Analyze response
263 if (dwResult == SNMP_ERR_SUCCESS)
264 {
265 if ((pRespPDU->GetNumVariables() > 0) &&
266 (pRespPDU->GetErrorCode() == SNMP_PDU_ERR_SUCCESS))
267 {
268 SNMP_Variable *pVar = pRespPDU->GetVariable(0);
269
270 if ((pVar->GetType() != ASN_NO_SUCH_OBJECT) &&
271 (pVar->GetType() != ASN_NO_SUCH_INSTANCE))
272 {
273 // Should we stop walking?
274 if ((pVar->GetName()->Length() < dwRootLen) ||
275 (memcmp(pdwRootName, pVar->GetName()->GetValue(), dwRootLen * sizeof(DWORD))))
276 {
277 bRunning = FALSE;
278 delete pRespPDU;
279 delete pRqPDU;
280 break;
281 }
282 memcpy(pdwName, pVar->GetName()->GetValue(),
283 pVar->GetName()->Length() * sizeof(DWORD));
284 dwNameLen = pVar->GetName()->Length();
285
286 // Call user's callback function for processing
287 pHandler(dwVersion, dwAddr, wPort, szCommunity, pVar, pTransport, pUserArg);
288 }
289 else
290 {
291 dwResult = SNMP_ERR_NO_OBJECT;
292 bRunning = FALSE;
293 }
294 }
295 else
296 {
297 if (pRespPDU->GetErrorCode() == SNMP_PDU_ERR_NO_SUCH_NAME)
298 dwResult = SNMP_ERR_NO_OBJECT;
299 else
300 dwResult = SNMP_ERR_AGENT;
301 bRunning = FALSE;
302 }
303 delete pRespPDU;
304 }
305 else
306 {
307 if (bVerbose)
308 WriteLog(MSG_SNMP_GET_ERROR, EVENTLOG_ERROR_TYPE, "d", dwResult);
309 bRunning = FALSE;
310 }
311 delete pRqPDU;
312 }
313 }
314 }
315
316 delete pTransport;
317 return dwResult;
318 }
319
320
321 //
322 // Handler for enumerating indexes
323 //
324
325 static void HandlerIndex(DWORD dwVersion, DWORD dwAddr, WORD wPort, const char *szCommunity,
326 SNMP_Variable *pVar, SNMP_Transport *pTransport, void *pArg)
327 {
328 if (((INTERFACE_LIST *)pArg)->iEnumPos < ((INTERFACE_LIST *)pArg)->iNumEntries)
329 ((INTERFACE_LIST *)pArg)->pInterfaces[((INTERFACE_LIST *)pArg)->iEnumPos].dwIndex = pVar->GetValueAsUInt();
330 ((INTERFACE_LIST *)pArg)->iEnumPos++;
331 }
332
333
334 //
335 // Handler for enumerating IP addresses
336 //
337
338 static void HandlerIpAddr(DWORD dwVersion, DWORD dwAddr, WORD wPort,
339 const char *szCommunity, SNMP_Variable *pVar,
340 SNMP_Transport *pTransport, void *pArg)
341 {
342 DWORD dwIndex, dwNetMask, dwNameLen;
343 DWORD oidName[MAX_OID_LEN];
344
345 dwNameLen = pVar->GetName()->Length();
346 memcpy(oidName, pVar->GetName()->GetValue(), dwNameLen * sizeof(DWORD));
347 oidName[dwNameLen - 5] = 3; // Retrieve network mask for this IP
348 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, NULL, oidName, dwNameLen,
349 &dwNetMask, sizeof(DWORD), FALSE, FALSE) != SNMP_ERR_SUCCESS)
350 return;
351
352 oidName[dwNameLen - 5] = 2; // Retrieve interface index for this IP
353 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, NULL, oidName, dwNameLen,
354 &dwIndex, sizeof(DWORD), FALSE, FALSE) == SNMP_ERR_SUCCESS)
355 {
356 int i;
357
358 for(i = 0; i < ((INTERFACE_LIST *)pArg)->iNumEntries; i++)
359 if (((INTERFACE_LIST *)pArg)->pInterfaces[i].dwIndex == dwIndex)
360 {
361 if (((INTERFACE_LIST *)pArg)->pInterfaces[i].dwIpAddr != 0)
362 {
363 // This interface entry already filled, so we have additional IP addresses
364 // on a single interface
365 ((INTERFACE_LIST *)pArg)->iNumEntries++;
366 ((INTERFACE_LIST *)pArg)->pInterfaces = (INTERFACE_INFO *)realloc(((INTERFACE_LIST *)pArg)->pInterfaces,
367 sizeof(INTERFACE_INFO) * ((INTERFACE_LIST *)pArg)->iNumEntries);
368 memcpy(&(((INTERFACE_LIST *)pArg)->pInterfaces[((INTERFACE_LIST *)pArg)->iNumEntries - 1]),
369 &(((INTERFACE_LIST *)pArg)->pInterfaces[i]), sizeof(INTERFACE_INFO));
370 if (strlen(((INTERFACE_LIST *)pArg)->pInterfaces[i].szName) < MAX_OBJECT_NAME - 4)
371 {
372 char szBuffer[8];
373
374 sprintf(szBuffer,":%d", ((INTERFACE_LIST *)pArg)->pInterfaces[i].iNumSecondary++);
375 strcat(((INTERFACE_LIST *)pArg)->pInterfaces[((INTERFACE_LIST *)pArg)->iNumEntries - 1].szName, szBuffer);
376 }
377 i = ((INTERFACE_LIST *)pArg)->iNumEntries - 1;
378 }
379 ((INTERFACE_LIST *)pArg)->pInterfaces[i].dwIpAddr = ntohl(pVar->GetValueAsUInt());
380 ((INTERFACE_LIST *)pArg)->pInterfaces[i].dwIpNetMask = dwNetMask;
381 break;
382 }
383 }
384 }
385
386
387 //
388 // Get interface list via SNMP
389 //
390
391 INTERFACE_LIST *SnmpGetInterfaceList(DWORD dwVersion, DWORD dwAddr, WORD wPort,
392 const char *szCommunity, DWORD dwNodeType)
393 {
394 long i, iNumIf;
395 char szOid[128], szBuffer[256];
396 INTERFACE_LIST *pIfList = NULL;
397 BOOL bSuccess = FALSE;
398
399 // Get number of interfaces
400 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, ".1.3.6.1.2.1.2.1.0", NULL, 0,
401 &iNumIf, sizeof(long), FALSE, FALSE) != SNMP_ERR_SUCCESS)
402 return NULL;
403
404 // Create empty list
405 pIfList = (INTERFACE_LIST *)malloc(sizeof(INTERFACE_LIST));
406 pIfList->iNumEntries = iNumIf;
407 pIfList->iEnumPos = 0;
408 pIfList->pInterfaces = (INTERFACE_INFO *)malloc(sizeof(INTERFACE_INFO) * iNumIf);
409 memset(pIfList->pInterfaces, 0, sizeof(INTERFACE_INFO) * pIfList->iNumEntries);
410
411 // Gather interface indexes
412 if (SnmpEnumerate(dwVersion, dwAddr, wPort, szCommunity, ".1.3.6.1.2.1.2.2.1.1",
413 HandlerIndex, pIfList, FALSE) == SNMP_ERR_SUCCESS)
414 {
415 // Enumerate interfaces
416 for(i = 0; i < iNumIf; i++)
417 {
418 // Interface name
419 sprintf(szOid, ".1.3.6.1.2.1.2.2.1.2.%d", pIfList->pInterfaces[i].dwIndex);
420 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, szOid, NULL, 0,
421 pIfList->pInterfaces[i].szName, MAX_OBJECT_NAME,
422 FALSE, FALSE) != SNMP_ERR_SUCCESS)
423 break;
424
425 // Interface type
426 sprintf(szOid, ".1.3.6.1.2.1.2.2.1.3.%d", pIfList->pInterfaces[i].dwIndex);
427 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, szOid, NULL, 0,
428 &pIfList->pInterfaces[i].dwType, sizeof(DWORD),
429 FALSE, FALSE) != SNMP_ERR_SUCCESS)
430 break;
431
432 // MAC address
433 sprintf(szOid, ".1.3.6.1.2.1.2.2.1.6.%d", pIfList->pInterfaces[i].dwIndex);
434 memset(szBuffer, 0, MAC_ADDR_LENGTH);
435 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, szOid, NULL, 0,
436 szBuffer, 256, FALSE, TRUE) != SNMP_ERR_SUCCESS)
437 break;
438 memcpy(pIfList->pInterfaces[i].bMacAddr, szBuffer, MAC_ADDR_LENGTH);
439 }
440
441 if (i == iNumIf)
442 {
443 // Interface IP address'es and netmasks
444 if (SnmpEnumerate(dwVersion, dwAddr, wPort, szCommunity, ".1.3.6.1.2.1.4.20.1.1",
445 HandlerIpAddr, pIfList, FALSE) == SNMP_ERR_SUCCESS)
446 {
447 // Handle special cases
448 if (dwNodeType == NODE_TYPE_NORTEL_ACCELAR)
449 GetAccelarVLANIfList(dwVersion, dwAddr, wPort, szCommunity, pIfList);
450 bSuccess = TRUE;
451 }
452 }
453 }
454
455 if (bSuccess)
456 {
457 CleanInterfaceList(pIfList);
458 }
459 else
460 {
461 DestroyInterfaceList(pIfList);
462 pIfList = NULL;
463 }
464
465 return pIfList;
466 }
467
468
469 //
470 // Handler for ARP enumeration
471 //
472
473 static void HandlerArp(DWORD dwVersion, DWORD dwAddr, WORD wPort, const char *szCommunity,
474 SNMP_Variable *pVar, SNMP_Transport *pTransport, void *pArg)
475 {
476 DWORD oidName[MAX_OID_LEN], dwNameLen, dwIndex = 0;
477 BYTE bMac[64];
478
479 dwNameLen = pVar->GetName()->Length();
480 memcpy(oidName, pVar->GetName()->GetValue(), dwNameLen * sizeof(DWORD));
481
482 oidName[dwNameLen - 6] = 1; // Retrieve interface index
483 SnmpGet(dwVersion, dwAddr, wPort, szCommunity, NULL, oidName, dwNameLen, &dwIndex,
484 sizeof(DWORD), FALSE, FALSE);
485
486 oidName[dwNameLen - 6] = 2; // Retrieve MAC address for this IP
487 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, NULL, oidName, dwNameLen, bMac,
488 64, FALSE, FALSE) == SNMP_ERR_SUCCESS)
489 {
490 ((ARP_CACHE *)pArg)->dwNumEntries++;
491 ((ARP_CACHE *)pArg)->pEntries = (ARP_ENTRY *)realloc(((ARP_CACHE *)pArg)->pEntries,
492 sizeof(ARP_ENTRY) * ((ARP_CACHE *)pArg)->dwNumEntries);
493 ((ARP_CACHE *)pArg)->pEntries[((ARP_CACHE *)pArg)->dwNumEntries - 1].dwIpAddr = ntohl(pVar->GetValueAsUInt());
494 memcpy(((ARP_CACHE *)pArg)->pEntries[((ARP_CACHE *)pArg)->dwNumEntries - 1].bMacAddr, bMac, 6);
495 ((ARP_CACHE *)pArg)->pEntries[((ARP_CACHE *)pArg)->dwNumEntries - 1].dwIndex = dwIndex;
496 }
497 }
498
499
500 //
501 // Get ARP cache via SNMP
502 //
503
504 ARP_CACHE *SnmpGetArpCache(DWORD dwVersion, DWORD dwAddr, WORD wPort, const char *szCommunity)
505 {
506 ARP_CACHE *pArpCache;
507
508 pArpCache = (ARP_CACHE *)malloc(sizeof(ARP_CACHE));
509 if (pArpCache == NULL)
510 return NULL;
511
512 pArpCache->dwNumEntries = 0;
513 pArpCache->pEntries = NULL;
514
515 if (SnmpEnumerate(dwVersion, dwAddr, wPort, szCommunity, ".1.3.6.1.2.1.4.22.1.3",
516 HandlerArp, pArpCache, FALSE) != SNMP_ERR_SUCCESS)
517 {
518 DestroyArpCache(pArpCache);
519 pArpCache = NULL;
520 }
521 return pArpCache;
522 }
523
524
525 //
526 // Get interface status via SNMP
527 // Possible return values can be NORMAL, CRITICAL, DISABLED, TESTING and UNKNOWN
528 //
529
530 int SnmpGetInterfaceStatus(DWORD dwVersion, DWORD dwNodeAddr, WORD wPort,
531 char *pszCommunity, DWORD dwIfIndex)
532 {
533 DWORD dwAdminStatus = 0, dwOperStatus = 0;
534 int iStatus;
535 char szOid[256];
536
537 // Interface administrative status
538 sprintf(szOid, ".1.3.6.1.2.1.2.2.1.7.%ld", dwIfIndex);
539 SnmpGet(dwVersion, dwNodeAddr, wPort, pszCommunity, szOid, NULL, 0,
540 &dwAdminStatus, sizeof(DWORD), FALSE, FALSE);
541
542 switch(dwAdminStatus)
543 {
544 case 3:
545 iStatus = STATUS_TESTING;
546 break;
547 case 2:
548 iStatus = STATUS_DISABLED;
549 break;
550 case 1: // Interface administratively up, check operational status
551 // Get interface operational status
552 sprintf(szOid, ".1.3.6.1.2.1.2.2.1.8.%ld", dwIfIndex);
553 SnmpGet(dwVersion, dwNodeAddr, wPort, pszCommunity, szOid, NULL, 0,
554 &dwOperStatus, sizeof(DWORD), FALSE, FALSE);
555 switch(dwOperStatus)
556 {
557 case 3:
558 iStatus = STATUS_TESTING;
559 break;
560 case 2: // Interface is down
561 iStatus = STATUS_CRITICAL;
562 break;
563 case 1:
564 iStatus = STATUS_NORMAL;
565 break;
566 default:
567 iStatus = STATUS_UNKNOWN;
568 break;
569 }
570 break;
571 default:
572 iStatus = STATUS_UNKNOWN;
573 break;
574 }
575 return iStatus;
576 }
577
578
579 //
580 // Handler for route enumeration
581 //
582
583 static void HandlerRoute(DWORD dwVersion, DWORD dwAddr, WORD wPort,
584 const char *szCommunity, SNMP_Variable *pVar,
585 SNMP_Transport *pTransport, void *pArg)
586 {
587 DWORD oidName[MAX_OID_LEN], dwNameLen;
588 ROUTE route;
589
590 dwNameLen = pVar->GetName()->Length();
591 memcpy(oidName, pVar->GetName()->GetValue(), dwNameLen * sizeof(DWORD));
592 route.dwDestAddr = ntohl(pVar->GetValueAsUInt());
593
594 oidName[dwNameLen - 5] = 2; // Interface index
595 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, NULL, oidName, dwNameLen,
596 &route.dwIfIndex, sizeof(DWORD), FALSE, FALSE) != SNMP_ERR_SUCCESS)
597 return;
598
599 oidName[dwNameLen - 5] = 7; // Next hop
600 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, NULL, oidName, dwNameLen,
601 &route.dwNextHop, sizeof(DWORD), FALSE, FALSE) != SNMP_ERR_SUCCESS)
602 return;
603
604 oidName[dwNameLen - 5] = 8; // Route type
605 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, NULL, oidName, dwNameLen,
606 &route.dwRouteType, sizeof(DWORD), FALSE, FALSE) != SNMP_ERR_SUCCESS)
607 return;
608
609 oidName[dwNameLen - 5] = 11; // Destination mask
610 if (SnmpGet(dwVersion, dwAddr, wPort, szCommunity, NULL, oidName, dwNameLen,
611 &route.dwDestMask, sizeof(DWORD), FALSE, FALSE) != SNMP_ERR_SUCCESS)
612 return;
613
614 ((ROUTING_TABLE *)pArg)->iNumEntries++;
615 ((ROUTING_TABLE *)pArg)->pRoutes =
616 (ROUTE *)realloc(((ROUTING_TABLE *)pArg)->pRoutes,
617 sizeof(ROUTE) * ((ROUTING_TABLE *)pArg)->iNumEntries);
618 memcpy(&((ROUTING_TABLE *)pArg)->pRoutes[((ROUTING_TABLE *)pArg)->iNumEntries - 1],
619 &route, sizeof(ROUTE));
620 }
621
622
623 //
624 // Get routing table via SNMP
625 //
626
627 ROUTING_TABLE *SnmpGetRoutingTable(DWORD dwVersion, DWORD dwAddr, WORD wPort,
628 const char *szCommunity)
629 {
630 ROUTING_TABLE *pRT;
631
632 pRT = (ROUTING_TABLE *)malloc(sizeof(ROUTING_TABLE));
633 if (pRT == NULL)
634 return NULL;
635
636 pRT->iNumEntries = 0;
637 pRT->pRoutes = NULL;
638
639 if (SnmpEnumerate(dwVersion, dwAddr, wPort, szCommunity, ".1.3.6.1.2.1.4.21.1.1",
640 HandlerRoute, pRT, FALSE) != SNMP_ERR_SUCCESS)
641 {
642 DestroyRoutingTable(pRT);
643 pRT = NULL;
644 }
645 return pRT;
646 }