2 //=============================================================================
6 * Pdu class implementation. Encapsulation of an SMI Protocol
7 * Data Unit (PDU) in C++.
9 * @author Peter E MellquistMichael R MacFaden mrm@cisco.com - rework & ACE port
11 //=============================================================================
13 /*===================================================================
15 Hewlett-Packard Company
17 ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
18 Permission to use, copy, modify, distribute and/or sell this software
19 and/or its documentation is hereby granted without fee. User agrees
20 to display the above copyright notice and this license notice in all
21 copies of the software and any documentation of the software. User
22 agrees to assume all liability for the use of the software; Hewlett-Packard
23 makes no representations about the suitability of this software for any
24 purpose. It is provided "AS-IS without warranty of any kind,either express
25 or implied. User hereby grants a royalty-free license to any and all
26 derivatives based upon this software code base.
27 =====================================================================*/
29 #include "asnmp/snmp.h"
30 #include "asnmp/pdu.h" // include Pdu class definition
31 #include "ace/OS_NS_string.h"
32 #include "ace/OS_NS_stdio.h"
34 //=====================[ constructor no args ]=========================
35 Pdu::Pdu(): vb_count_(0), error_status_(0), error_index_(0),
36 validity_(0), request_id_(0), pdu_type_(0), notify_timestamp_(0),
41 //=====================[ constructor with vbs_ and count ]==============
42 Pdu::Pdu( Vb
* pvbs
, const int pvb_count
): vb_count_(0), error_index_(0),
43 validity_(0), request_id_(0), pdu_type_(0), notify_timestamp_(0),
46 int z
= 0; // looping variable
49 if ( pvb_count
== 0) {
54 // check for over then max
55 if ( pvb_count
> MAX_VBS
) {
60 // loop through and assign internal vbs_
61 for (z
= 0;z
< pvb_count
; z
++) {
63 ACE_NEW(vbs_
[z
], Vb( pvbs
[z
]));
67 // assign the vb count
68 vb_count_
= pvb_count
;
73 //=====================[ constructor with another Pdu instance ]========
74 Pdu::Pdu( const Pdu
&pdu
): vb_count_(0),
75 error_index_(0), validity_(0), request_id_(0), pdu_type_(0),
76 notify_timestamp_(0), output_(0)
82 //=====================[ destructor ]====================================
90 //=====================[ assignment to another Pdu object overloaded ]===
91 Pdu
& Pdu::operator=( const Pdu
&pdu
)
96 int z
; // looping variable
98 // Initialize all mv's
99 error_status_
= pdu
.error_status_
;
100 error_index_
= pdu
.error_index_
;
101 request_id_
= pdu
.request_id_
;
102 pdu_type_
= pdu
.pdu_type_
;
103 notify_id_
= pdu
.notify_id_
;
104 notify_timestamp_
= pdu
.notify_timestamp_
;
105 notify_enterprise_
= pdu
.notify_enterprise_
;
109 for ( z
= 0;z
< vb_count_
; z
++)
113 // check for zero case
114 if ( pdu
.vb_count_
== 0) {
118 // loop through and fill em up
119 for (z
= 0; z
< pdu
.vb_count_
; z
++) {
121 ACE_NEW_RETURN(vbs_
[z
], Vb ( *(pdu
.vbs_
[z
])), *this);
125 vb_count_
= pdu
.vb_count_
;
129 // append operator, appends a string
130 Pdu
& Pdu::operator+=( Vb
&vb
)
133 if ( vb_count_
+ 1 > MAX_VBS
)
138 ACE_NEW_RETURN(vbs_
[vb_count_
], Vb (vb
), *this);
145 // return self reference
149 // return fomatted version of this object
150 const char * Pdu::to_string()
152 // determine how big a buffer and allocate it
153 const int HEADER_STR
= 100;
154 unsigned size
= HEADER_STR
; // header takes up this much room
157 for ( z
= 0; z
< vb_count_
; z
++)
158 size
+= ACE_OS::strlen(vbs_
[z
]->to_string());
160 ACE_NEW_RETURN(output_
, char[size
], "");
162 // print pdu header info
163 ACE_OS::sprintf(output_
, "pdu: valid: %d type:%d, req:%d, cnt: %d, err stat: %d \
164 err idx: %d\n", validity_
, pdu_type_
, (int) request_id_
,
165 vb_count_
, error_status_
, error_index_
);
167 // now append vb pairs in this object
168 for ( z
= 0; z
< vb_count_
; z
++) {
169 ACE_OS::strcat(output_
, vbs_
[z
]->to_string());
170 ACE_OS::strcat(output_
, "\n\t");
177 //=====================[ extract Vbs from Pdu ]==========================
178 // how do you know that the caler has enough memory???
179 // should I self allocate this in here and require the
180 // caller then to free it up at soem later time
181 int Pdu::get_vblist( Vb
* pvbs
, const int pvb_count
)
183 if ((!pvbs
) || ( pvb_count
< 0) || ( pvb_count
> vb_count_
))
186 // loop through all vbs_ and assign to params
188 for (z
= 0; z
< pvb_count
; z
++)
194 //=====================[ deposit Vbs ]===================================
195 int Pdu::set_vblist( Vb
* pvbs
, const int pvb_count
)
197 // if invalid then don't destroy
198 if ((!pvbs
) || ( pvb_count
< 0) || ( pvb_count
> MAX_VBS
))
201 // free up current vbs_
203 for ( z
= 0; z
< vb_count_
; z
++)
207 // check for zero case
208 if ( pvb_count
== 0) {
217 // loop through all vbs_ and reassign them
218 for ( z
= 0; z
< pvb_count
; z
++) {
220 ACE_NEW_RETURN(vbs_
[z
], Vb (pvbs
[z
]), 0);
224 vb_count_
= pvb_count
;
226 // clear error status and index since no longer valid
227 // request id may still apply so don't reassign it
235 //===================[ get a particular vb ]=============================
236 // here the caller has already instantiated a vb object
237 // index is zero based
238 int Pdu::get_vb( Vb
&vb
, const int index
) const
240 // can't have an index less than 0
244 // can't ask for something not there
245 if ( index
> (vb_count_
- 1))
254 //===================[ set a particular vb ]=============================
255 int Pdu::set_vb( Vb
&vb
, const int index
)
257 // can't set a vb at index less than 0
261 // can't ask for something not there
262 if ( index
> (vb_count_
- 1))
265 // delete what is there
270 ACE_NEW_RETURN(vbs_
[index
], Vb (vb
), 0);
276 //=====================[ return number of vbs_ ]==========================
277 int Pdu::get_vb_count() const
282 //=====================[ return the error status ]=======================
283 int Pdu::get_error_status() const
285 return error_status_
;
288 const char *Pdu::agent_error_reason()
290 int pdu_err
= get_error_status();
291 if (pdu_err
== 0) // any real error?
292 return "not in error state";
294 int n_vbs
= get_vb_count();
296 get_vb(bad
, get_error_index() -1); // not zero based??
297 const char *pmsg
= Snmp::error_string(get_error_status());
298 const char *id
= bad
.to_string_oid();
299 const char *val
= bad
.to_string_value();
300 const int HDR_SZ
= 100;
303 int size
= ACE_OS::strlen(pmsg
) + ACE_OS::strlen(id
) +
305 ACE_NEW_RETURN(output_
, char[size
+ HDR_SZ
], "");
308 ACE_OS::sprintf(output_
,
309 "FAIL PDU REPORT: pdu id: %lu vb cnt: %d vb idx: %d\n"
310 " msg: %s vb oid: %s value: %s\n",
311 get_request_id(), n_vbs
, get_error_index(),
317 //=====================[ set the error status ]==========================
319 void set_error_status( Pdu
*pdu
, const int status
)
322 pdu
->error_status_
= status
;
325 //=====================[ return the error index ]========================
326 int Pdu::get_error_index() const
331 //=====================[ set the error index ]===========================
333 void set_error_index( Pdu
*pdu
, const int index
)
336 pdu
->error_index_
= index
;
339 //=====================[ clear error status ]=============================
340 void clear_error_status( Pdu
*pdu
)
343 pdu
->error_status_
= 0;
346 //=====================[ clear error index ]==============================
347 void clear_error_index( Pdu
*pdu
)
350 pdu
->error_index_
= 0;
353 //=====================[ return the request id ]==========================
354 unsigned long Pdu::get_request_id() const
359 //=====================[ set the request id ]=============================
361 void set_request_id( Pdu
*pdu
, const unsigned long rid
)
364 pdu
->request_id_
= rid
;
367 //=====================[ returns validity_ of Pdu instance ]===============
368 int Pdu::valid() const
373 //=====================[ get the pdu type ]===============================
374 unsigned short Pdu::get_type()const
380 void Pdu::set_type( unsigned short type
)
386 // trim off the last vb
387 int Pdu::trim(const int p
)
391 // verify that lp is legal
392 if ( lp
< 0 || lp
> vb_count_
)
396 if ( vb_count_
> 0) {
397 delete vbs_
[vb_count_
- 1];
406 // delete a Vb anywhere within the Pdu
407 int Pdu::delete_vb( const int p
)
409 // position has to be in range
410 if (( p
< 0) || ( p
> (vb_count_
- 1)))
416 for ( int z
=p
;z
< (vb_count_
-1);z
++) {
424 void Pdu::delete_all_vbs()
426 for ( int z
= 0; z
< vb_count_
; z
++)
432 // set notify timestamp
433 void Pdu::set_notify_timestamp( const TimeTicks
& timestamp
)
435 notify_timestamp_
= timestamp
;
439 // get notify timestamp
440 void Pdu::get_notify_timestamp( TimeTicks
& timestamp
) const
442 timestamp
= notify_timestamp_
;
446 void Pdu::set_notify_id( const Oid id
)
452 void Pdu::get_notify_id( Oid
&id
) const
457 // set the notify enterprise
458 void Pdu::set_notify_enterprise( const Oid
&enterprise
)
460 notify_enterprise_
= enterprise
;
463 // get the notify enterprise
464 void Pdu::get_notify_enterprise( Oid
& enterprise
) const
466 enterprise
= notify_enterprise_
;
469 // ------ class VbIter -------------------
470 VbIter::VbIter(Pdu
& pdu
): idx_(-1), pdu_(&pdu
)
474 // returns 1 if ok, else 0 if none left
475 int VbIter::next(Vb
& vb
)
479 pdu_
->get_vb(vb
, idx_
++);
483 if (idx_
< pdu_
->get_vb_count()) {
484 pdu_
->get_vb(vb
, idx_
++);
487 return 0; // non left