1 /*_############################################################################
6 _## -----------------------------------------------
7 _## Copyright (c) 2001-2010 Jochen Katz, Frank Fock
9 _## This software is based on SNMP++2.6 from Hewlett Packard:
11 _## Copyright (c) 1996
12 _## Hewlett-Packard Company
14 _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
15 _## Permission to use, copy, modify, distribute and/or sell this software
16 _## and/or its documentation is hereby granted without fee. User agrees
17 _## to display the above copyright notice and this license notice in all
18 _## copies of the software and any documentation of the software. User
19 _## agrees to assume all liability for the use of the software;
20 _## Hewlett-Packard and Jochen Katz make no representations about the
21 _## suitability of this software for any purpose. It is provided
22 _## "AS-IS" without warranty of any kind, either express or implied. User
23 _## hereby grants a royalty-free license to any and all derivatives based
24 _## upon this software code base.
26 _## Stuttgart, Germany, Thu Sep 2 00:07:47 CEST 2010
28 _##########################################################################*/
29 /*===================================================================
32 Hewlett-Packard Company
34 ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
35 Permission to use, copy, modify, distribute and/or sell this software
36 and/or its documentation is hereby granted without fee. User agrees
37 to display the above copyright notice and this license notice in all
38 copies of the software and any documentation of the software. User
39 agrees to assume all liability for the use of the software; Hewlett-Packard
40 makes no representations about the suitability of this software for any
41 purpose. It is provided "AS-IS" without warranty of any kind,either express
42 or implied. User hereby grants a royalty-free license to any and all
43 derivatives based upon this software code base.
48 PDU CLASS IMPLEMENTATION
50 DESIGN + AUTHOR: Peter E Mellquist
53 Pdu class implementation. Encapsulation of an SMI Protocol
54 Data Unit (PDU) in C++.
56 =====================================================================*/
57 char pdu_cpp_version[]="@(#) SNMP++ $Id: pdu.cpp 209 2006-01-07 20:02:34Z katz $";
59 #include "snmp_pp/pdu.h" // include Pdu class definition
60 #include "snmp_pp/usm_v3.h"
61 #include "snmp_pp/vb.h"
62 #include "snmp_pp/v3.h"
64 #ifdef SNMP_PP_NAMESPACE
68 #define PDU_INITIAL_SIZE 25
70 //=====================[ constructor no args ]=========================
72 : vbs(0), vbs_size(0), vb_count(0), error_status(0), error_index(0),
73 validity(true), request_id(0), pdu_type(0), notify_timestamp(0),
74 v1_trap_address_set(false)
76 , security_level(SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV),
77 message_id(0), maxsize_scopedpdu(0)
82 //=====================[ constructor with vbs and count ]==============
83 Pdu::Pdu(Vb* pvbs, const int pvb_count)
84 : vbs(0), vbs_size(0), vb_count(0), error_status(0), error_index(0),
85 validity(true), request_id(0), pdu_type(0), notify_timestamp(0),
86 v1_trap_address_set(false)
88 , security_level(SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV),
89 message_id(0), maxsize_scopedpdu(0)
92 if (pvb_count == 0) return; // zero is ok
94 vbs = new Vb*[pvb_count];
104 // loop through and assign internal vbs
105 for (int z = 0; z < pvb_count; ++z)
108 vbs[z] = new Vb(pvbs[z]);
112 if ((vbs[z]) && !vbs[z]->valid())
118 if (vbs[z] == 0) // check for new fail
120 for (int y = 0; y < z; ++y) delete vbs[y]; // free vbs
126 vb_count = pvb_count; // assign the vb count
129 //=====================[ destructor ]====================================
132 for (int z = 0; z < vb_count; ++z)
146 //=====================[ assignment to another Pdu object overloaded ]===
147 Pdu& Pdu::operator=(const Pdu &pdu)
149 if (this == &pdu) return *this; // check for self assignment
151 // Initialize all mv's
152 error_status = pdu.error_status;
153 error_index = pdu.error_index;
154 request_id = pdu.request_id;
155 pdu_type = pdu.pdu_type;
156 notify_id = pdu.notify_id;
157 notify_timestamp = pdu.notify_timestamp;
158 notify_enterprise = pdu.notify_enterprise;
160 security_level = pdu.security_level;
161 message_id = pdu.message_id;
162 context_name = pdu.context_name;
163 context_engine_id = pdu.context_engine_id;
164 maxsize_scopedpdu = pdu.maxsize_scopedpdu;
166 if (pdu.v1_trap_address_set)
168 v1_trap_address = pdu.v1_trap_address;
169 v1_trap_address_set = true;
172 v1_trap_address_set = false;
177 for (int z = 0; z < vb_count; ++z) delete vbs[z];
180 // check for zero case
181 if (pdu.vb_count == 0) return *this;
184 if (vbs_size < pdu.vb_count)
187 vbs = new Vb*[pdu.vb_count];
189 vbs_size = pdu.vb_count;
198 // loop through and fill em up
199 for (int y = 0; y < pdu.vb_count; ++y)
201 vbs[y] = new Vb(*(pdu.vbs[y]));
203 if ((vbs[y]) && !vbs[y]->valid())
211 for (int x = 0; x < y; ++x) delete vbs[x]; // free vbs
217 vb_count = pdu.vb_count;
221 // append operator, appends a variable binding
222 Pdu& Pdu::operator+=(const Vb &vb)
224 if (!vb.valid()) return *this; // dont add invalid Vbs
226 if (vb_count + 1 > vbs_size)
228 if (!extend_vbs()) return *this;
231 vbs[vb_count] = new Vb(vb); // add the new one
233 if (vbs[vb_count]) // up the vb count on success
235 if (vbs[vb_count]->valid())
238 validity = true; // set up validity
242 delete vbs[vb_count];
247 return *this; // return self reference
250 //=====================[ extract Vbs from Pdu ]==========================
251 int Pdu::get_vblist(Vb* pvbs, const int pvb_count) const
253 if ((!pvbs) || (pvb_count < 0) || (pvb_count > vb_count))
256 // loop through all vbs and assign to params
257 for (int z = 0; z < pvb_count; ++z)
260 if (!pvbs[z].valid())
267 //=====================[ deposit Vbs ]===================================
268 int Pdu::set_vblist(Vb* pvbs, const int pvb_count)
270 // if invalid then don't destroy
271 if (((!pvbs) && (pvb_count > 0)) ||
275 // free up current vbs
276 for (int z = 0; z < vb_count; ++z) delete vbs[z];
279 // check for zero case
290 if (vbs_size < pvb_count)
293 vbs = new Vb*[pvb_count];
295 vbs_size = pvb_count;
304 // loop through all vbs and reassign them
305 for (int y = 0; y < pvb_count; ++y)
309 vbs[y] = new Vb(pvbs[y]);
310 if ((vbs[y]) && !vbs[y]->valid())
322 for (int x = 0; x < y; ++x) delete vbs[x]; // free vbs
328 vb_count = pvb_count;
330 // clear error status and index since no longer valid
331 // request id may still apply so don't reassign it
339 //===================[ get a particular vb ]=============================
340 // here the caller has already instantiated a vb object
341 // index is zero based
342 int Pdu::get_vb(Vb &vb, const int index) const
344 if (index < 0) return false; // can't have an index less than 0
345 if (index >= vb_count) return false; // can't ask for something not there
347 vb = *vbs[index]; // asssign it
352 //===================[ set a particular vb ]=============================
353 int Pdu::set_vb(Vb &vb, const int index)
355 if (index < 0) return false; // can't have an index less than 0
356 if (index >= vb_count) return false; // can't ask for something not there
357 if (!vb.valid()) return false; // don't set invalid vbs
359 Vb *victim = vbs[index]; // save in case new fails
360 vbs[index] = new Vb(vb);
363 if (vbs[index]->valid())
382 // trim off the last vb
383 int Pdu::trim(const int count)
385 // verify that count is legal
386 if ((count < 0) || (count > vb_count)) return false;
394 delete vbs[vb_count-1];
403 // delete a Vb anywhere within the Pdu
404 int Pdu::delete_vb(const int p)
406 // position has to be in range
407 if ((p<0) || (p > vb_count - 1)) return false;
409 delete vbs[p]; // safe to remove it
411 for (int z = p; z < vb_count - 1; ++z)
420 // Get the SNMPv1 trap address
421 int Pdu::get_v1_trap_address(GenAddress &address) const
423 if (v1_trap_address_set == false)
426 address = v1_trap_address;
430 // Set the SNMPv1 trap address
431 int Pdu::set_v1_trap_address(const Address &address)
433 v1_trap_address = address;
434 v1_trap_address_set = (v1_trap_address.valid() == true);
436 return v1_trap_address_set;
439 int Pdu::get_asn1_length() const
443 // length for all vbs
444 for (int i = 0; i < vb_count; ++i)
445 length += vbs[i]->get_asn1_length();
448 if (length < 0x80) length += 2;
449 else if (length <= 0xFF) length += 3;
450 else if (length <= 0xFFFF) length += 4;
451 else if (length <= 0xFFFFFF) length += 5;
454 // req id, error status, error index
455 SnmpInt32 i32(request_id ? request_id : PDU_MAX_RID);
456 length += i32.get_asn1_length();
458 length += i32.get_asn1_length();
460 length += i32.get_asn1_length();
462 // header for data_pdu
463 if (length < 0x80) length += 2;
464 else if (length <= 0xFF) length += 3;
465 else if (length <= 0xFFFF) length += 4;
466 else if (length <= 0xFFFFFF) length += 5;
470 // now the scopedpdu part sequence (4), context engine, id context name
471 length += 4 + 2 + context_engine_id.len() + 2 + context_name.len();
473 // An encrypted message is transported as an octet string
474 if (security_level == SNMP_SECURITY_LEVEL_AUTH_PRIV)
476 // assume that encryption increases the data to a multiple of 16
477 int mod = length % 16;
478 if (mod) length += 16 - mod;
487 // extend the vbs array
488 bool Pdu::extend_vbs()
492 vbs = new Vb*[PDU_INITIAL_SIZE];
495 vbs_size = PDU_INITIAL_SIZE;
503 vbs = new Vb*[vbs_size * 2];
510 for (int y = 0; y < vb_count; ++y)
517 // Clear all members of the object
524 notify_timestamp = 0;
526 notify_enterprise.clear();
527 v1_trap_address_set = false;
530 for (int z = 0; z < vb_count; ++z) delete vbs[z];
534 security_level = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
536 maxsize_scopedpdu = 0;
537 context_name.clear();
538 context_engine_id.clear();
542 // Does the type of response match the type of request
543 bool Pdu::match_type(const int request, const int response)
548 case sNMP_PDU_GETNEXT:
550 case sNMP_PDU_GETBULK:
551 case sNMP_PDU_INFORM:
553 if ((response == sNMP_PDU_RESPONSE) ||
554 (response == sNMP_PDU_REPORT))
556 if ((response == sNMP_PDU_GET) ||
557 (response == sNMP_PDU_GETNEXT) ||
558 (response == sNMP_PDU_SET) ||
559 (response == sNMP_PDU_GETBULK) ||
560 (response == sNMP_PDU_INFORM) ||
561 (response == sNMP_PDU_V1TRAP) ||
562 (response == sNMP_PDU_TRAP))
564 debugprintf(0, "Unknown response pdu type (%d).", response);
568 case sNMP_PDU_REPORT:
569 case sNMP_PDU_RESPONSE:
570 case sNMP_PDU_V1TRAP:
577 debugprintf(0, "Unknown request pdu type (%d).", request);
583 #ifdef SNMP_PP_NAMESPACE
584 }; // end of namespace Snmp_pp