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