13 yi.zhou 1.1 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 // Author: Yi Zhou, Hewlett-Packard Company (Yi.Zhou@hp.com)
33 //
34 yi.zhou 1.1 // Modified By:
35 //
36 //%/////////////////////////////////////////////////////////////////////////////
37
38 #include <Pegasus/Common/Packer.h>
39 #include <Pegasus/Common/Tracer.h>
40 #include "snmpDeliverTrap_netsnmp.h"
41
42 PEGASUS_NAMESPACE_BEGIN
43
44 void snmpDeliverTrap_netsnmp::deliverTrap(
45 const String& trapOid,
46 const String& securityName,
47 const String& targetHost,
48 const Uint16& targetHostFormat,
49 const String& otherTargetHostFormat,
50 const Uint32& portNumber,
51 const Uint16& snmpVersion,
52 const String& engineID,
53 const Array<String>& vbOids,
54 const Array<String>& vbTypes,
55 yi.zhou 1.1 const Array<String>& vbValues)
56 {
57
58 PEG_METHOD_ENTER (TRC_IND_HANDLER,
59 "snmpDeliverTrap_netsnmp::deliverTrap");
60
61 void *sessionHandle;
62 struct snmp_session snmpSession, *sessionPtr;
63
64 struct snmp_pdu *snmpPdu;
65
66 // Creates a SNMP session
67 _createSession(targetHost, portNumber, securityName, snmpSession,
68 sessionHandle, sessionPtr);
69
70 try
71 {
72 _createPdu(snmpVersion, trapOid, sessionPtr, snmpPdu);
73 }
74 catch (...)
75 {
76 yi.zhou 1.1 _destroySession(sessionHandle);
77
78 PEG_METHOD_EXIT ();
79
80 throw;
81 }
82
83 // Pack OIDs into the PDU
84 try
85 {
86 _packOidsIntoPdu(vbOids, vbTypes, vbValues, snmpPdu);
87 }
88 catch (Exception& e)
89 {
90 PEG_TRACE_STRING (TRC_DISCARDED_DATA, Tracer::LEVEL2,
91 e.getMessage ());
92
93 Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
94 Logger::WARNING,
95 _MSG_PACK_CIM_PROPERTY_TO_PDU_FAILED_KEY,
96 _MSG_PACK_CIM_PROPERTY_TO_PDU_FAILED,
97 yi.zhou 1.1 e.getMessage());
98 }
99 catch (...)
100 {
101 PEG_TRACE_STRING (TRC_DISCARDED_DATA, Tracer::LEVEL2,
102 "Snmp Indication Handler failed to pack a CIM "
103 "Property into the SNMP PDU: Unknown exception.");
104 }
105
106 // Send the trap to the destination
107 if (snmp_sess_send(sessionHandle, snmpPdu) == 0)
108 {
109 Sint32 libErr, sysErr;
110 char *errStr;
111
112 // snmp_sess_send failed
113 // get library, system errno
114 snmp_sess_error(sessionHandle, &libErr, &sysErr, &errStr);
115
116 String exceptionStr = _MSG_SESSION_SEND_FAILED;
117 exceptionStr.append (errStr);
118 yi.zhou 1.1
119 free(errStr);
120
121 _destroySession(sessionHandle);
122
123 PEG_METHOD_EXIT ();
124
125 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_FAILED,
126 MessageLoaderParms(_MSG_SESSION_SEND_FAILED_KEY,
127 exceptionStr));
128 }
129
130 _destroySession(sessionHandle);
131
132 PEG_METHOD_EXIT ();
133
134 }
135
136 // Creates a SNMP session
137 void snmpDeliverTrap_netsnmp::_createSession(
138 const String & targetHost,
139 yi.zhou 1.1 Uint32 portNumber,
140 const String & securityName,
141 snmp_session & snmpSession,
142 void *&sessionHandle,
143 snmp_session *&sessionPtr)
144 {
145 PEG_METHOD_ENTER (TRC_IND_HANDLER,
146 "snmpDeliverTrap_netsnmp::_createSession");
147
148 Sint32 libErr, sysErr;
149 char *errStr;
150 String exceptionStr;
151
|
165 yi.zhou 1.1 // Initialize the mib reader
166 netsnmp_set_mib_directory("");
167 init_mib();
168
169 // Initializes the SNMP library
170 init_snmp("snmpIndicationHandler");
171
172 // Prepares a struct snmp_session that will be used for a set of
173 // SNMP transactions
174 snmp_sess_init(&snmpSession);
175
176 // windows32 specific initialization (is a NOOP on unix)
177 SOCK_STARTUP;
178
179 CString targetHostCStr = targetHost.getCString();
180
181 // peername has format: targetHost:portNumber
182 snmpSession.peername = (char *)malloc((size_t)(strlen(targetHostCStr)+
183 1+32));
184 sprintf(snmpSession.peername, "%s:%u", (const char*)targetHostCStr,
185 portNumber);
186 yi.zhou 1.1 sessionHandle = snmp_sess_open(&snmpSession);
187
188 if (sessionHandle == NULL)
189 {
190 exceptionStr = _MSG_SESSION_OPEN_FAILED;
191
192 // Get library, system errno
193 snmp_sess_error(&snmpSession, &libErr, &sysErr, &errStr);
194
195 exceptionStr.append(errStr);
196
197 free(errStr);
198
199 SOCK_CLEANUP;
200
201 PEG_METHOD_EXIT ();
202
203 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_FAILED,
204 MessageLoaderParms(_MSG_SESSION_OPEN_FAILED_KEY,
205 exceptionStr));
206
207 yi.zhou 1.1 }
208
209 try
210 {
211 // get the snmp_session pointer
212 sessionPtr = snmp_sess_session(sessionHandle);
213 if (sessionPtr == NULL)
214 {
215 exceptionStr = _MSG_GET_SESSION_POINT_FAILED;
216
217 // Get library, system errno
218 snmp_sess_error(&snmpSession, &libErr, &sysErr, &errStr);
219
220 exceptionStr.append(errStr);
221
222 free(errStr);
223
224 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_FAILED,
225 MessageLoaderParms(_MSG_GET_SESSION_POINTER_FAILED_KEY,
226 exceptionStr));
227 }
228 yi.zhou 1.1
229 // Community Name, default is public
230 String communityName;
231 if (securityName.size() == 0)
232 {
233 communityName.assign("public");
234 }
235 else
236 {
237 communityName = securityName;
238 }
239
240 if (snmpSession.peername)
241 {
242 free(snmpSession.peername);
243 }
244
245 if (sessionPtr->community)
246 {
247 free(sessionPtr->community);
248 }
249 yi.zhou 1.1
250 CString communityNameCStr = communityName.getCString();
251 size_t communityNameLen = strlen(communityNameCStr);
252
253 sessionPtr->community = (u_char*)malloc(communityNameLen);
254
255 memcpy(sessionPtr->community, (const char *)communityNameCStr,
256 communityNameLen);
257 sessionPtr->community_len = communityNameLen;
258 }
259 catch (...)
260 {
261 _destroySession(sessionHandle);
262
263 PEG_METHOD_EXIT ();
264 throw;
265 }
266
267 PEG_METHOD_EXIT ();
268 }
269
270 yi.zhou 1.1 // Creates a SNMP session
271 void snmpDeliverTrap_netsnmp::_destroySession(
272 void *sessionHandle)
273 {
274 PEG_METHOD_ENTER (TRC_IND_HANDLER,
275 "snmpDeliverTrap_netsnmp::_destroySession");
276
277 snmp_sess_close(sessionHandle);
278
279 SOCK_CLEANUP;
280
281 PEG_METHOD_EXIT ();
282 }
283
284 // Creates a SNMP TRAP PDU
285 void snmpDeliverTrap_netsnmp::_createPdu(
286 Uint16 snmpVersion,
287 const String& trapOid,
288 snmp_session *&sessionPtr,
289 snmp_pdu *& snmpPdu)
290 {
291 yi.zhou 1.1
292 PEG_METHOD_ENTER (TRC_IND_HANDLER,
293 "snmpDeliverTrap_netsnmp::_createPdu");
294
295 oid _SYSTEM_UP_TIME_OID [] = {1,3,6,1,2,1,1,3,0};
296 oid _SNMPTRAP_OID [] = {1,3,6,1,6,3,1,1,4,1,0};
297
298 in_addr_t *pduInAddr;
299
300 switch (snmpVersion)
301 {
302 case _SNMPv1_TRAP:
303 {
304
305 sessionPtr->version = SNMP_VERSION_1;
306
307 // Create the PDU
308 snmpPdu = snmp_pdu_create(SNMP_MSG_TRAP);
309
310 // Failed to create pdu
311 if (!snmpPdu)
312 yi.zhou 1.1 {
313 PEG_METHOD_EXIT ();
314
315 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_FAILED,
316 MessageLoaderParms(_MSG_PDU_CREATE_FAILED_KEY,
317 _MSG_PDU_CREATE_FAILED));
318 }
319
320 // Make sure that the v1 trap PDU includes the local IP address
321 pduInAddr = (in_addr_t*) snmpPdu->agent_addr;
322 *pduInAddr = get_myaddr();
323
324 // get system up time
325 snmpPdu->time = get_uptime();
326
327 // Pack trap information into the PDU
328 try
329 {
330 _packTrapInfoIntoPdu(trapOid, snmpPdu);
331 }
332 catch (CIMException& e)
333 yi.zhou 1.1 {
334 PEG_TRACE_STRING (TRC_DISCARDED_DATA, Tracer::LEVEL2,
335 e.getMessage ());
336 Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
337 Logger::WARNING,
338 _MSG_PACK_TRAP_INFO_INTO_PDU_FAILED_KEY,
339 _MSG_PACK_TRAP_INFO_INTO_PDU_FAILED,
340 e.getMessage());
341 }
342
343 break;
344 }
345 case _SNMPv2C_TRAP:
346 {
347 sessionPtr->version = SNMP_VERSION_2c;
348
349 // Create the PDU
350 snmpPdu = snmp_pdu_create(SNMP_MSG_TRAP2);
351
352 // Failed to create pdu
353 if (!snmpPdu)
354 yi.zhou 1.1 {
355 PEG_METHOD_EXIT ();
356
357 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_FAILED,
358 MessageLoaderParms(_MSG_PDU_CREATE_FAILED_KEY,
359 _MSG_PDU_CREATE_FAILED));
360 }
361
362 // Add sysUpTime to the PDU
363 char sysUpTime[32];
364 sprintf(sysUpTime, "%ld", get_uptime());
365
366 Sint32 retCode;
367 retCode = snmp_add_var(snmpPdu, _SYSTEM_UP_TIME_OID,
368 OID_LENGTH(_SYSTEM_UP_TIME_OID), 't',
369 sysUpTime);
370
371
372 // Failed to add sysUpTime to the pdu
373 if (retCode != 0)
374 {
375 yi.zhou 1.1 String errMsg = snmp_api_errstring(retCode);
376
377 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
378 "Failed to add sysUpTime to pdu: " +
379 errMsg);
380 Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
381 Logger::WARNING,
382 _MSG_ADD_SYSUPTIME_TO_PDU_FAILED_KEY,
383 _MSG_ADD_SYSUPTIME_TO_PDU_FAILED,
384 errMsg);
385 }
386
387 // Add snmp trap to the PDU
388 retCode = snmp_add_var(snmpPdu, _SNMPTRAP_OID, OID_LENGTH(
389 _SNMPTRAP_OID), 'o', trapOid.getCString());
390
391 // Failed to add snmp trap to the pdu
392 if (retCode != 0)
393 {
394 String errMsg = snmp_api_errstring(retCode);
395
396 yi.zhou 1.1 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
397 "Failed to add snmp trap to pdu: " +
398 errMsg);
399 Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
400 Logger::WARNING,
401 _MSG_ADD_SNMP_TRAP_TO_PDU_FAILED_KEY,
402 _MSG_ADD_SNMP_TRAP_TO_PDU_FAILED,
403 errMsg);
404 }
405
406 break;
407 }
408 default:
409 {
410 PEG_METHOD_EXIT ();
411
412 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_NOT_SUPPORTED,
413 MessageLoaderParms(_MSG_VERSION_NOT_SUPPORTED_KEY,
414 _MSG_VERSION_NOT_SUPPORTED));
415 break;
416 }
417 yi.zhou 1.1 }
418
419 PEG_METHOD_EXIT ();
420 }
421
422
423 // Pack trap information into the PDU
424 void snmpDeliverTrap_netsnmp::_packTrapInfoIntoPdu(
425 const String & trapOid,
426 snmp_pdu * snmpPdu)
427 {
428 PEG_METHOD_ENTER (TRC_IND_HANDLER,
429 "snmpDeliverTrap_netsnmp::_packTrapInfoIntoPdu");
430
431 oid enterpriseOid[MAX_OID_LEN];
432 size_t enterpriseOidLength;
433
434 Array<String> standard_traps;
435
436 standard_traps.append(String("1.3.6.1.6.3.1.1.5.1"));
437 standard_traps.append(String("1.3.6.1.6.3.1.1.5.2"));
438 yi.zhou 1.1 standard_traps.append(String("1.3.6.1.6.3.1.1.5.3"));
439 standard_traps.append(String("1.3.6.1.6.3.1.1.5.4"));
440 standard_traps.append(String("1.3.6.1.6.3.1.1.5.5"));
441 standard_traps.append(String("1.3.6.1.6.3.1.1.5.6"));
442
443 Array<const char *> oidSubIdentifiers;
444
445 CString trapOidCStr = trapOid.getCString();
446
447 char * trapOidCopy = strdup(trapOidCStr);
448
449 #if !defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC)
450 char *last;
451 for (const char* p = strtok_r(trapOidCopy, ".", &last); p;
452 p=strtok_r(NULL, ".", &last))
453 #else
454 for (const char* p = strtok(trapOidCopy, "."); p; p=strtok(NULL, "."))
455 #endif
456 {
457 oidSubIdentifiers.append(p);
458 }
459 yi.zhou 1.1
460 long genTrap = 0;
461 long specTrap = 0;
462
463 enterpriseOidLength = MAX_OID_LEN;
464
465 char * numericEntOid = (char *) malloc(strlen(trapOidCStr));
466 if (Contains(standard_traps, trapOid))
467 {
468 //
469 // if the trapOid is one of the standard traps,
470 // then the SNMPV1 enterprise parameter must be set
471 // to the value of the trapOid, the generic-trap
472 // parameter must be set to one of (0 - 5), and the
473 // specific-trap parameter must be set to 0
474 //
475
476 // Convert trapOid from numeric form to a list of subidentifiers
477 if (read_objid((const char*)trapOidCStr, enterpriseOid,
478 &enterpriseOidLength) == 0)
479 {
480 yi.zhou 1.1 // Failed to parse trapOid
481
482 PEG_METHOD_EXIT ();
483 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_FAILED,
484 MessageLoaderParms(_MSG_READ_OBJID_FAILED_KEY,
485 _MSG_READ_OBJID_FAILED,
486 trapOid));
487 }
488
489 // the generic trap is last sub-identifier of the
490 // trapOid minus 1
491 snmpPdu->trap_type =
492 atoi(oidSubIdentifiers[oidSubIdentifiers.size() - 1]) - 1;
493 snmpPdu->specific_type = 0;
494 }
495 else
496 {
497 //
498 // if the trapOid is not one of the standard traps:
499 // then 1) the generic-trap parameter must be set to 6,
500 // 2) if the next-to-last sub-identifier of the
501 yi.zhou 1.1 // trapOid is zero, then the SNMPV1 enterprise
502 // parameter is the trapOid with the last 2
503 // sub-identifiers removed, otherwise, the
504 // SNMPV1 enterprise parameter is the trapOid
505 // with the last sub-identifier removed;
506 // 3) the SNMPv1 specific-trap parameter is the last
507 // sub-identifier of the trapOid;
508 //
509
510 snmpPdu->trap_type = 6;
511
512 snmpPdu->specific_type =
513 atoi(oidSubIdentifiers[oidSubIdentifiers.size()-1]);
514
515 strcpy(numericEntOid, oidSubIdentifiers[0]);
516 for (Uint32 i = 1; i < oidSubIdentifiers.size()-2; i++)
517 {
518 strcat(numericEntOid, ".");
519 strcat(numericEntOid, oidSubIdentifiers[i]);
520 }
521
522 yi.zhou 1.1 if (oidSubIdentifiers[oidSubIdentifiers.size()-2] != "0")
523 {
524 strcat(numericEntOid, ".");
525 strcat(numericEntOid,
526 oidSubIdentifiers[oidSubIdentifiers.size()-2]);
527 }
528
529 // Convert ent from numeric form to a list of subidentifiers
530 if (read_objid(numericEntOid, enterpriseOid,
531 &enterpriseOidLength) == 0)
532 {
533 // Failed to parse numericEntOid
534
535 PEG_METHOD_EXIT ();
536
537 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_FAILED,
538 MessageLoaderParms(_MSG_READ_ENTOID_FAILED_KEY,
539 _MSG_READ_ENTOID_FAILED,
540 String(numericEntOid)));
541 }
542
543 yi.zhou 1.1 }
544
545 snmpPdu->enterprise = (oid*) malloc(enterpriseOidLength * sizeof(oid));
546 memcpy(snmpPdu->enterprise, enterpriseOid,
547 enterpriseOidLength * sizeof(oid));
548
549 snmpPdu->enterprise_length = enterpriseOidLength;
550
551 free(trapOidCopy);
552 free(numericEntOid);
553
554 PEG_METHOD_EXIT ();
555 }
556
557 // Pack oids into the PDU
558 void snmpDeliverTrap_netsnmp::_packOidsIntoPdu(
559 const Array<String>& vbOids,
560 const Array<String>& vbTypes,
561 const Array<String>& vbValues,
562 snmp_pdu * snmpPdu)
563 {
564 yi.zhou 1.1
565 PEG_METHOD_ENTER (TRC_IND_HANDLER,
566 "snmpDeliverTrap_netsnmp::_packOidsIntoPdu");
567
568 char dataType;
569 oid vbOid[MAX_OID_LEN];
570 size_t vbOidLength = MAX_OID_LEN;
571
572 for (Uint32 i=0; i < vbOids.size(); i++)
573 {
574 if (vbTypes[i] == "OctetString")
575 {
576 dataType = 's';
577 }
578 else if (vbTypes[i] == "Integer")
579 {
580 dataType = 'i';
581 }
582 else if (vbTypes[i] == "OID")
583 {
584 dataType = 'o';
585 yi.zhou 1.1 }
586 else
587 {
588 // Integer, OctetString, and OID are supported SNMP Data Types
589 // for the CIM Property
590
591 PEG_METHOD_EXIT ();
592
593 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_FAILED,
594 MessageLoaderParms(_MSG_UNSUPPORTED_SNMP_DATA_TYPE_KEY,
595 _MSG_UNSUPPORTED_SNMP_DATA_TYPE,
596 vbTypes[i]));
597
598 }
599
600 // Convert oid of a CIM property from numeric form to a list of
601 // subidentifiers
602 if (read_objid((const char*)vbOids[i].getCString(), vbOid,
603 &vbOidLength) == 0)
604 {
605 // Failed to parse vbOids
606 yi.zhou 1.1
607 PEG_METHOD_EXIT ();
608
609 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_FAILED,
610 MessageLoaderParms(_MSG_PARSE_CIM_PROPERTY_OID_FAILED_KEY,
611 _MSG_PARSE_CIM_PROPERTY_OID_FAILED,
612 vbOids[i]));
613 }
614
615 Sint32 retCode;
616 retCode = snmp_add_var(snmpPdu, vbOid, vbOidLength, dataType,
617 vbValues[i].getCString());
618
619 // Failed to add vbOid to the pdu
620 if (retCode != 0)
621 {
622 PEG_METHOD_EXIT ();
623
624 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_FAILED,
625 MessageLoaderParms(_MSG_ADD_VAR_TO_PDU_FAILED_KEY,
626 _MSG_ADD_VAR_TO_PDU_FAILED,
627 yi.zhou 1.1 vbOids[i],
628 String(snmp_api_errstring(retCode))));
629
630 }
631 }
632
633 PEG_METHOD_EXIT ();
634 }
635
636 PEGASUS_NAMESPACE_END
|