36977284dca3915401438e67fe9ee3ac3a8119e3
[public/netxms.git] / src / snmp / libnxsnmp / variable.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** SNMP support library
4 ** Copyright (C) 2003, 2004, 2005, 2006, 2007 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: variable.cpp
21 **
22 **/
23
24 #include "libnxsnmp.h"
25
26
27 //
28 // SNMP_Variable default constructor
29 //
30
31 SNMP_Variable::SNMP_Variable()
32 {
33 m_pName = NULL;
34 m_pValue = NULL;
35 m_dwType = ASN_NULL;
36 m_dwValueLength = 0;
37 }
38
39
40 //
41 // Create variable of ASN_NULL type
42 //
43
44 SNMP_Variable::SNMP_Variable(TCHAR *pszName)
45 {
46 DWORD dwLength, *pdwOid;
47
48 m_pValue = NULL;
49 m_dwType = ASN_NULL;
50 m_dwValueLength = 0;
51
52 pdwOid = (DWORD *)malloc(sizeof(DWORD) * MAX_OID_LEN);
53 dwLength = SNMPParseOID(pszName, pdwOid, MAX_OID_LEN);
54 m_pName = new SNMP_ObjectId(dwLength, pdwOid);
55 free(pdwOid);
56 }
57
58
59 //
60 // Create variable of ASN_NULL type
61 //
62
63 SNMP_Variable::SNMP_Variable(DWORD *pdwName, DWORD dwNameLen)
64 {
65 m_pValue = NULL;
66 m_dwType = ASN_NULL;
67 m_dwValueLength = 0;
68 m_pName = new SNMP_ObjectId(dwNameLen, pdwName);
69 }
70
71
72 //
73 // SNMP_Variable destructor
74 //
75
76 SNMP_Variable::~SNMP_Variable()
77 {
78 delete m_pName;
79 safe_free(m_pValue);
80 }
81
82
83 //
84 // Parse variable record in PDU
85 //
86
87 BOOL SNMP_Variable::Parse(BYTE *pData, DWORD dwVarLength)
88 {
89 BYTE *pbCurrPos;
90 DWORD dwType, dwLength, dwIdLength;
91 SNMP_OID *oid;
92 BOOL bResult = FALSE;
93
94 // Object ID
95 if (!BER_DecodeIdentifier(pData, dwVarLength, &dwType, &dwLength, &pbCurrPos, &dwIdLength))
96 return FALSE;
97 if (dwType != ASN_OBJECT_ID)
98 return FALSE;
99
100 oid = (SNMP_OID *)malloc(sizeof(SNMP_OID));
101 memset(oid, 0, sizeof(SNMP_OID));
102 if (BER_DecodeContent(dwType, pbCurrPos, dwLength, (BYTE *)oid))
103 {
104 m_pName = new SNMP_ObjectId(oid->dwLength, oid->pdwValue);
105 dwVarLength -= dwLength + dwIdLength;
106 pbCurrPos += dwLength;
107 bResult = TRUE;
108 }
109 safe_free(oid->pdwValue);
110 free(oid);
111
112 if (bResult)
113 {
114 bResult = FALSE;
115 if (BER_DecodeIdentifier(pbCurrPos, dwVarLength, &m_dwType, &dwLength, &pbCurrPos, &dwIdLength))
116 {
117 switch(m_dwType)
118 {
119 case ASN_OBJECT_ID:
120 oid = (SNMP_OID *)malloc(sizeof(SNMP_OID));
121 memset(oid, 0, sizeof(SNMP_OID));
122 if (BER_DecodeContent(m_dwType, pbCurrPos, dwLength, (BYTE *)oid))
123 {
124 m_dwValueLength = oid->dwLength * sizeof(DWORD);
125 m_pValue = (BYTE *)oid->pdwValue;
126 bResult = TRUE;
127 }
128 else
129 {
130 safe_free(oid->pdwValue);
131 }
132 free(oid);
133 break;
134 case ASN_INTEGER:
135 case ASN_COUNTER32:
136 case ASN_GAUGE32:
137 case ASN_TIMETICKS:
138 case ASN_UINTEGER32:
139 m_dwValueLength = sizeof(DWORD);
140 m_pValue = (BYTE *)malloc(8);
141 bResult = BER_DecodeContent(m_dwType, pbCurrPos, dwLength, m_pValue);
142 break;
143 case ASN_COUNTER64:
144 m_dwValueLength = sizeof(QWORD);
145 m_pValue = (BYTE *)malloc(16);
146 bResult = BER_DecodeContent(m_dwType, pbCurrPos, dwLength, m_pValue);
147 break;
148 default:
149 m_dwValueLength = dwLength;
150 m_pValue = (BYTE *)nx_memdup(pbCurrPos, dwLength);
151 bResult = TRUE;
152 break;
153 }
154 }
155 }
156
157 return bResult;
158 }
159
160
161 //
162 // Get value as unsigned integer
163 //
164
165 DWORD SNMP_Variable::GetValueAsUInt(void)
166 {
167 DWORD dwValue;
168
169 switch(m_dwType)
170 {
171 case ASN_INTEGER:
172 case ASN_COUNTER32:
173 case ASN_GAUGE32:
174 case ASN_TIMETICKS:
175 case ASN_UINTEGER32:
176 case ASN_IP_ADDR:
177 dwValue = *((DWORD *)m_pValue);
178 break;
179 case ASN_COUNTER64:
180 dwValue = (DWORD)(*((QWORD *)m_pValue));
181 break;
182 default:
183 dwValue = 0;
184 break;
185 }
186
187 return dwValue;
188 }
189
190
191 //
192 // Get value as signed integer
193 //
194
195 LONG SNMP_Variable::GetValueAsInt(void)
196 {
197 LONG iValue;
198
199 switch(m_dwType)
200 {
201 case ASN_INTEGER:
202 case ASN_COUNTER32:
203 case ASN_GAUGE32:
204 case ASN_TIMETICKS:
205 case ASN_UINTEGER32:
206 case ASN_IP_ADDR:
207 iValue = *((LONG *)m_pValue);
208 break;
209 case ASN_COUNTER64:
210 iValue = (LONG)(*((QWORD *)m_pValue));
211 break;
212 default:
213 iValue = 0;
214 break;
215 }
216
217 return iValue;
218 }
219
220
221 //
222 // Get value as string
223 //
224
225 TCHAR *SNMP_Variable::GetValueAsString(TCHAR *pszBuffer, DWORD dwBufferSize)
226 {
227 DWORD dwLen;
228
229 if ((pszBuffer == NULL) || (dwBufferSize == 0))
230 return NULL;
231
232 switch(m_dwType)
233 {
234 case ASN_INTEGER:
235 _sntprintf(pszBuffer, dwBufferSize, _T("%d"), *((LONG *)m_pValue));
236 break;
237 case ASN_COUNTER32:
238 case ASN_GAUGE32:
239 case ASN_TIMETICKS:
240 case ASN_UINTEGER32:
241 _sntprintf(pszBuffer, dwBufferSize, _T("%u"), *((DWORD *)m_pValue));
242 break;
243 case ASN_COUNTER64:
244 _sntprintf(pszBuffer, dwBufferSize, UINT64_FMT, *((QWORD *)m_pValue));
245 break;
246 case ASN_IP_ADDR:
247 if (dwBufferSize >= 16)
248 IpToStr(ntohl(*((DWORD *)m_pValue)), pszBuffer);
249 else
250 pszBuffer[0] = 0;
251 break;
252 case ASN_OBJECT_ID:
253 SNMPConvertOIDToText(m_dwValueLength / sizeof(DWORD), (DWORD *)m_pValue,
254 pszBuffer, dwBufferSize);
255 break;
256 case ASN_OCTET_STRING:
257 dwLen = min(dwBufferSize - 1, m_dwValueLength);
258 #ifdef UNICODE
259 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (char *)m_pValue, dwLen,
260 pszBuffer, dwBufferSize);
261 #else
262 memcpy(pszBuffer, m_pValue, dwLen);
263 #endif
264 pszBuffer[dwLen] = 0;
265 break;
266 default:
267 pszBuffer[0] = 0;
268 break;
269 }
270 return pszBuffer;
271 }
272
273
274 //
275 // Get value as object id
276 //
277
278 SNMP_ObjectId *SNMP_Variable::GetValueAsObjectId(void)
279 {
280 SNMP_ObjectId *oid = NULL;
281
282 if (m_dwType == ASN_OBJECT_ID)
283 {
284 oid = new SNMP_ObjectId(m_dwValueLength / sizeof(DWORD), (DWORD *)m_pValue);
285 }
286 return oid;
287 }
288
289
290 //
291 // Get value as MAC address
292 //
293
294 TCHAR *SNMP_Variable::GetValueAsMACAddr(TCHAR *pszBuffer)
295 {
296 int i;
297 TCHAR *pszPos;
298
299 // MAC address usually encoded as octet string
300 if ((m_dwType == ASN_OCTET_STRING) && (m_dwValueLength >= 6))
301 {
302 for(i = 0, pszPos = pszBuffer; i < 6; i++, pszPos += 3)
303 _sntprintf(pszPos, 4, _T("%02X:"), m_pValue[i]);
304 *(pszPos - 1) = 0;
305 }
306 else
307 {
308 _tcscpy(pszBuffer, _T("00:00:00:00:00:00"));
309 }
310 return pszBuffer;
311 }
312
313
314 //
315 // Get value as IP address
316 //
317
318 TCHAR *SNMP_Variable::GetValueAsIPAddr(TCHAR *pszBuffer)
319 {
320 // Ignore type and check only length
321 if (m_dwValueLength >= 4)
322 {
323 IpToStr(ntohl(*((DWORD *)m_pValue)), pszBuffer);
324 }
325 else
326 {
327 _tcscpy(pszBuffer, _T("0.0.0.0"));
328 }
329 return pszBuffer;
330 }
331
332
333 //
334 // Encode variable using BER
335 // Normally buffer provided should be at least m_dwValueLength + (name_length * 4) + 12 bytes
336 // Return value is number of bytes actually used in buffer
337 //
338
339 DWORD SNMP_Variable::Encode(BYTE *pBuffer, DWORD dwBufferSize)
340 {
341 DWORD dwBytes, dwWorkBufSize;
342 BYTE *pWorkBuf;
343
344 dwWorkBufSize = m_dwValueLength + m_pName->Length() * 4 + 16;
345 pWorkBuf = (BYTE *)malloc(dwWorkBufSize);
346 dwBytes = BER_Encode(ASN_OBJECT_ID, (BYTE *)m_pName->GetValue(),
347 m_pName->Length() * sizeof(DWORD),
348 pWorkBuf, dwWorkBufSize);
349 dwBytes += BER_Encode(m_dwType, m_pValue, m_dwValueLength,
350 pWorkBuf + dwBytes, dwWorkBufSize - dwBytes);
351 dwBytes = BER_Encode(ASN_SEQUENCE, pWorkBuf, dwBytes, pBuffer, dwBufferSize);
352 free(pWorkBuf);
353 return dwBytes;
354 }
355
356
357 //
358 // Set variable from string
359 //
360
361 void SNMP_Variable::SetValueFromString(DWORD dwType, TCHAR *pszValue)
362 {
363 DWORD *pdwBuffer, dwLen;
364
365 m_dwType = dwType;
366 switch(m_dwType)
367 {
368 case ASN_INTEGER:
369 m_dwValueLength = sizeof(LONG);
370 m_pValue = (BYTE *)realloc(m_pValue, m_dwValueLength);
371 *((LONG *)m_pValue) = _tcstol(pszValue, NULL, 0);
372 break;
373 case ASN_COUNTER32:
374 case ASN_GAUGE32:
375 case ASN_TIMETICKS:
376 case ASN_UINTEGER32:
377 m_dwValueLength = sizeof(DWORD);
378 m_pValue = (BYTE *)realloc(m_pValue, m_dwValueLength);
379 *((DWORD *)m_pValue) = _tcstoul(pszValue, NULL, 0);
380 break;
381 case ASN_COUNTER64:
382 m_dwValueLength = sizeof(QWORD);
383 m_pValue = (BYTE *)realloc(m_pValue, m_dwValueLength);
384 *((QWORD *)m_pValue) = _tcstoull(pszValue, NULL, 0);
385 break;
386 case ASN_IP_ADDR:
387 m_dwValueLength = sizeof(DWORD);
388 m_pValue = (BYTE *)realloc(m_pValue, m_dwValueLength);
389 *((DWORD *)m_pValue) = _t_inet_addr(pszValue);
390 break;
391 case ASN_OBJECT_ID:
392 pdwBuffer = (DWORD *)malloc(sizeof(DWORD) * 256);
393 dwLen = SNMPParseOID(pszValue, pdwBuffer, 256);
394 if (dwLen > 0)
395 {
396 m_dwValueLength = dwLen * sizeof(DWORD);
397 safe_free(m_pValue);
398 m_pValue = (BYTE *)nx_memdup(pdwBuffer, m_dwValueLength);
399 }
400 else
401 {
402 // OID parse error, set to .ccitt.zeroDotZero (.0.0)
403 m_dwValueLength = sizeof(DWORD) * 2;
404 m_pValue = (BYTE *)realloc(m_pValue, m_dwValueLength);
405 memset(m_pValue, 0, m_dwValueLength);
406 }
407 break;
408 case ASN_OCTET_STRING:
409 m_dwValueLength = (DWORD)_tcslen(pszValue);
410 #ifdef UNICODE
411 m_pValue = (BYTE *)realloc(m_pValue, m_dwValueLength);
412 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
413 pszValue, m_dwValueLength, (char *)m_pValue,
414 m_dwValueLength, NULL, NULL);
415 #else
416 safe_free(m_pValue);
417 m_pValue = (BYTE *)nx_memdup(pszValue, m_dwValueLength);
418 #endif
419 break;
420 default:
421 break;
422 }
423 }