]> git.stg.codes - ssmd.git/blob - 3rdparty/snmp++/src/snmpmsg.cpp
Fix build on osx.
[ssmd.git] / 3rdparty / snmp++ / src / snmpmsg.cpp
1 /*_############################################################################
2   _## 
3   _##  snmpmsg.cpp  
4   _##
5   _##  SNMP++v3.2.25
6   _##  -----------------------------------------------
7   _##  Copyright (c) 2001-2010 Jochen Katz, Frank Fock
8   _##
9   _##  This software is based on SNMP++2.6 from Hewlett Packard:
10   _##  
11   _##    Copyright (c) 1996
12   _##    Hewlett-Packard Company
13   _##  
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. 
25   _##  
26   _##  Stuttgart, Germany, Thu Sep  2 00:07:47 CEST 2010 
27   _##  
28   _##########################################################################*/
29 /*===================================================================
30
31   Copyright (c) 1996
32   Hewlett-Packard Company
33
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.
44
45   SNMP++ S N M P M S G . C P P
46
47   SNMPMESSAGE CLASS DEFINITION
48
49   DESIGN + AUTHOR:  Peter E Mellquist
50
51   DESCRIPTION:      ASN.1       encoding / decoding class
52 =====================================================================*/
53 char snmpmsg_cpp_version[]="#(@) SNMP++ $Id: snmpmsg.cpp 1542 2009-05-29 11:38:48Z katz $";
54
55 #if defined(_AIX)
56 #include <unistd.h>
57 #endif
58 #if defined(__APPLE__)
59 #include <unistd.h>
60 #include <netinet/in.h>
61 #include <arpa/inet.h>
62 #endif
63 #include <stdio.h>
64
65 #include "snmp_pp/config_snmp_pp.h"
66 #include "snmp_pp/snmpmsg.h"                    // header file for SnmpMessage
67 #include "snmp_pp/oid_def.h"                    // changed (Frank Fock)
68 #include "snmp_pp/log.h"
69 #include "snmp_pp/vb.h"
70 #include "snmp_pp/usm_v3.h"
71
72 #ifdef SNMP_PP_NAMESPACE
73 namespace Snmp_pp {
74 #endif
75
76 #define MAX_LEN_COMMUNITY 254
77
78 const coldStartOid coldStart;
79 const warmStartOid warmStart;
80 const linkDownOid linkDown;
81 const linkUpOid linkUp;
82 const authenticationFailureOid authenticationFailure;
83 const egpNeighborLossOid egpNeighborLoss;
84 const snmpTrapEnterpriseOid snmpTrapEnterprise;
85
86 //------------[ convert SNMP++ VB to WinSNMP smiVALUE ]----------------
87 int convertVbToSmival( const Vb &tempvb, SmiVALUE *smival )
88 {
89   smival->syntax = tempvb.get_syntax();
90   switch ( smival->syntax ) {
91
92     // case sNMP_SYNTAX_NULL
93   case sNMP_SYNTAX_NULL:
94   case sNMP_SYNTAX_NOSUCHOBJECT:
95   case sNMP_SYNTAX_NOSUCHINSTANCE:
96   case sNMP_SYNTAX_ENDOFMIBVIEW:
97     break;
98
99     // case sNMP_SYNTAX_INT32:
100   case sNMP_SYNTAX_INT:
101     tempvb.get_value(smival->value.sNumber);
102     break;
103
104     //    case sNMP_SYNTAX_UINT32:
105   case sNMP_SYNTAX_GAUGE32:
106   case sNMP_SYNTAX_CNTR32:
107   case sNMP_SYNTAX_TIMETICKS:
108     //  case sNMP_SYNTAX_UINT32:
109     tempvb.get_value(smival->value.uNumber);
110     break;
111
112     // case Counter64
113   case sNMP_SYNTAX_CNTR64:
114     {
115       Counter64 c64;
116       tempvb.get_value(c64);
117       smival->value.hNumber.hipart = c64.high();
118       smival->value.hNumber.lopart = c64.low();
119     }
120     break;
121
122   case sNMP_SYNTAX_BITS:
123   case sNMP_SYNTAX_OCTETS:
124   case sNMP_SYNTAX_OPAQUE:
125   case sNMP_SYNTAX_IPADDR:
126     {
127       OctetStr os;
128       tempvb.get_value(os);
129       smival->value.string.ptr = NULL;
130       smival->value.string.len = os.len();
131       if ( smival->value.string.len > 0 )
132       {
133         smival->value.string.ptr
134           = (SmiLPBYTE) new  unsigned char [smival->value.string.len];
135         if ( smival->value.string.ptr )
136         {
137           for (int i=0; i<(int) smival->value.string.len ; i++)
138             smival->value.string.ptr[i] = os[i];
139         }
140         else
141         {
142           smival->syntax = sNMP_SYNTAX_NULL;  // invalidate the smival
143           return SNMP_CLASS_RESOURCE_UNAVAIL;
144         }
145       }
146     }
147     break;
148
149   case sNMP_SYNTAX_OID:
150     {
151       Oid oid;
152       tempvb.get_value(oid);
153       smival->value.oid.ptr = NULL;
154       smival->value.oid.len = oid.len();
155       if ( smival->value.oid.len > 0 )
156       {
157         smival->value.oid.ptr
158           = (SmiLPUINT32) new unsigned long [ smival->value.oid.len];
159         if ( smival->value.oid.ptr )
160         {
161           for (int i=0; i<(int)smival->value.oid.len ; i++)
162             smival->value.oid.ptr[i] = oid[i];
163         }
164         else
165         {
166           smival->syntax = sNMP_SYNTAX_NULL;  // invalidate the smival
167           return SNMP_CLASS_RESOURCE_UNAVAIL;
168         }
169       }
170     }
171     break;
172
173   default:
174     return SNMP_CLASS_INTERNAL_ERROR;
175   }
176   return SNMP_CLASS_SUCCESS;
177 }
178
179 // free a SMI value
180 void freeSmivalDescriptor( SmiVALUE *smival )
181 {
182   switch ( smival->syntax ) {
183   case sNMP_SYNTAX_OCTETS:
184   case sNMP_SYNTAX_OPAQUE:
185   case sNMP_SYNTAX_IPADDR:
186   case sNMP_SYNTAX_BITS:                    // obsoleted in SNMPv2 Draft Std
187     delete [] smival->value.string.ptr;
188     break;
189
190   case sNMP_SYNTAX_OID:
191     delete [] smival->value.oid.ptr;
192     break;
193   }
194   smival->syntax = sNMP_SYNTAX_NULL;
195 }
196
197 #ifdef _SNMPv3
198
199 int SnmpMessage::unloadv3( Pdu &pdu,                // Pdu returned
200                            snmp_version &version,   // version
201                            OctetStr &engine_id,     // optional v3
202                            OctetStr &security_name, // optional v3
203                            long int &security_model,
204                            UdpAddress &from_addr,
205                            Snmp &snmp_session)
206 {
207   OctetStr tmp;
208   return unload(pdu, tmp, version, &engine_id,
209                 &security_name, &security_model, &from_addr, &snmp_session);
210 }
211
212 #endif
213
214 int SnmpMessage::load(const Pdu &cpdu,
215                       const OctetStr &community,
216                       const snmp_version version,
217                       const OctetStr* engine_id,
218                       const OctetStr* security_name,
219                       const int security_model)
220 {
221   int status;
222   const Pdu *pdu = &cpdu;
223   Pdu temppdu;
224
225   // make sure pdu is valid
226   if ( !pdu->valid())
227     return SNMP_CLASS_INVALID_PDU;
228
229   // create a raw pdu
230   snmp_pdu *raw_pdu;
231   raw_pdu = snmp_pdu_create( (int) pdu->get_type());
232
233   Oid enterprise;
234
235   // load it up
236   raw_pdu->reqid = pdu->get_request_id();
237 #ifdef _SNMPv3
238   raw_pdu->msgid = pdu->get_message_id();
239 #endif
240   raw_pdu->errstat= (unsigned long) pdu->get_error_status();
241   raw_pdu->errindex= (unsigned long) pdu->get_error_index();
242
243   // if its a V1 trap then load up other values
244   // for v2, use normal pdu format
245   if (raw_pdu->command == sNMP_PDU_V1TRAP)
246   {
247     // DON'T forget about the v1 trap agent address (changed by Frank Fock)
248     GenAddress gen_addr;
249     IpAddress ip_addr;
250     int addr_set = FALSE;
251
252     if (pdu->get_v1_trap_address(gen_addr))
253     {
254       /* User did set the v1 trap address */
255       if ((gen_addr.get_type() != Address::type_ip) &&
256           (gen_addr.get_type() != Address::type_udp) )
257       {
258         LOG_BEGIN(ERROR_LOG | 4);
259         LOG("SNMPMessage: Bad v1 trap address type in pdu");
260         LOG(gen_addr.get_type());
261         LOG_END;
262
263         snmp_free_pdu( raw_pdu);
264         return SNMP_CLASS_INVALID_PDU;
265       }
266
267       ip_addr = gen_addr;
268       if (!ip_addr.valid())
269       {
270         LOG_BEGIN(ERROR_LOG | 1);
271         LOG("SNMPMessage: Copied v1 trap address not valid");
272         LOG_END;
273
274         snmp_free_pdu( raw_pdu);
275         return SNMP_CLASS_RESOURCE_UNAVAIL;
276       }
277       addr_set = TRUE;
278     }
279     else
280     {
281       /* User did not set the v1 trap address */
282       char addrString[256];
283       if (gethostname(addrString, 255) == 0)
284       {
285           ip_addr = addrString;
286           addr_set = TRUE;
287       }
288     }
289     struct sockaddr_in agent_addr;  // agent address socket struct
290     // prepare the agent address
291     memset(&agent_addr, 0, sizeof(agent_addr));
292     agent_addr.sin_family = AF_INET;
293     if (addr_set)
294     {
295       agent_addr.sin_addr.s_addr
296         = inet_addr(((IpAddress &)ip_addr).IpAddress::get_printable());
297       LOG_BEGIN(INFO_LOG | 7);
298       LOG("SNMPMessage: Setting v1 trap address");
299       LOG(((IpAddress &)ip_addr).IpAddress::get_printable());
300       LOG_END;
301     }
302     raw_pdu->agent_addr = agent_addr;
303
304     //-----[ compute generic trap value ]-------------------------------
305     // determine the generic value
306     // 0 - cold start
307     // 1 - warm start
308     // 2 - link down
309     // 3 - link up
310     // 4 - authentication failure
311     // 5 - egpneighborloss
312     // 6 - enterprise specific
313     Oid trapid;
314     pdu->get_notify_id( trapid);
315     if ( !trapid.valid() || trapid.len() < 2 )
316       {
317         snmp_free_pdu( raw_pdu);
318         return SNMP_CLASS_INVALID_NOTIFYID;
319       }
320     raw_pdu->specific_type=0;
321     if ( trapid == coldStart)
322       raw_pdu->trap_type = 0;  // cold start
323     else if ( trapid == warmStart)
324       raw_pdu->trap_type = 1;  // warm start
325     else if( trapid == linkDown)
326       raw_pdu->trap_type = 2;  // link down
327     else if ( trapid == linkUp)
328       raw_pdu->trap_type = 3;  // link up
329     else if ( trapid == authenticationFailure )
330       raw_pdu->trap_type = 4;  // authentication failure
331     else if ( trapid == egpNeighborLoss)
332       raw_pdu->trap_type = 5;  // egp neighbor loss
333     else {
334       raw_pdu->trap_type = 6;     // enterprise specific
335       // last oid subid is the specific value
336       // if 2nd to last subid is "0", remove it
337       // enterprise is always the notify oid prefix
338       raw_pdu->specific_type = (int) trapid[(int) (trapid.len()-1)];
339
340       trapid.trim(1);
341       if ( trapid[(int)(trapid.len()-1)] == 0 )
342         trapid.trim(1);
343       enterprise = trapid;
344     }
345
346     if ( raw_pdu->trap_type !=6)
347       pdu->get_notify_enterprise( enterprise);
348     if ( enterprise.len() >0) {
349       // note!!
350       // these are hooks into an SNMP++ oid
351       // and therefor the raw_pdu enterprise
352       // should not free them. null them out!!
353       SmiLPOID rawOid;
354       rawOid = enterprise.oidval();
355       raw_pdu->enterprise = rawOid->ptr;
356       raw_pdu->enterprise_length = (int) rawOid->len;
357     }
358
359     // timestamp
360     TimeTicks timestamp;
361     pdu->get_notify_timestamp( timestamp);
362     raw_pdu->time = ( unsigned long) timestamp;
363
364   }
365
366   // if its a v2 trap then we need to make a few adjustments
367   // vb #1 is the timestamp
368   // vb #2 is the id, represented as an Oid
369   if (( raw_pdu->command == sNMP_PDU_TRAP) ||
370       ( raw_pdu->command == sNMP_PDU_INFORM))
371   {
372     Vb tempvb;
373
374     temppdu = *pdu;
375     temppdu.trim(temppdu.get_vb_count());
376
377     // vb #1 is the timestamp
378     TimeTicks timestamp;
379     tempvb.set_oid(SNMP_MSG_OID_SYSUPTIME);   // sysuptime
380     pdu->get_notify_timestamp( timestamp);
381     tempvb.set_value ( timestamp);
382     temppdu += tempvb;
383
384     // vb #2 is the id
385     Oid trapid;
386     tempvb.set_oid(SNMP_MSG_OID_TRAPID);
387     pdu->get_notify_id( trapid);
388     tempvb.set_value( trapid);
389     temppdu += tempvb;
390
391     // append the remaining vbs
392     for (int z=0; z<pdu->get_vb_count(); z++) {
393       pdu->get_vb( tempvb,z);
394       temppdu += tempvb;
395     }
396
397     pdu = &temppdu;          // reassign the pdu to the temp one
398   }
399   // load up the payload
400   // for all Vbs in list, add them to the pdu
401   int vb_count;
402   Vb tempvb;
403   Oid tempoid;
404   SmiLPOID smioid;
405   SmiVALUE smival;
406
407   vb_count = pdu->get_vb_count();
408   for (int z=0;z<vb_count;z++) {
409     pdu->get_vb( tempvb,z);
410     tempvb.get_oid( tempoid);
411     smioid = tempoid.oidval();
412     // clear the value portion, in case its
413     // not already been done so by the app writer
414     // only do it in the case its a get,next or bulk
415     if ((raw_pdu->command == sNMP_PDU_GET) ||
416         (raw_pdu->command == sNMP_PDU_GETNEXT) ||
417         (raw_pdu->command == sNMP_PDU_GETBULK))
418       tempvb.set_null();
419     status = convertVbToSmival( tempvb, &smival );
420     if ( status != SNMP_CLASS_SUCCESS) {
421       snmp_free_pdu( raw_pdu);
422       return status;
423     }
424     // add the vb to the raw pdu
425     snmp_add_var( raw_pdu, smioid->ptr, (int) smioid->len, &smival);
426
427     freeSmivalDescriptor( &smival);
428   }
429
430   // ASN1 encode the pdu
431 #ifdef _SNMPv3
432   if (version == version3)
433   {
434     if ((!engine_id) || (!security_name))
435     {
436       LOG_BEGIN(ERROR_LOG | 4);
437       LOG("SNMPMessage: Need security name and engine id for v3 message");
438       LOG_END;
439
440       // prevention of SNMP++ Enterprise Oid death
441       if ( enterprise.len() >0) {
442         raw_pdu->enterprise = 0;
443         raw_pdu->enterprise_length=0;
444       }
445       snmp_free_pdu( raw_pdu);
446       return SNMP_CLASS_INVALID_TARGET;
447     }
448
449     status = v3MP::I->snmp_build(raw_pdu, databuff, (int *)&bufflen,
450                                  *engine_id, *security_name, security_model,
451                                  pdu->get_security_level(),
452                                  pdu->get_context_engine_id(),
453                                  pdu->get_context_name());
454     if (status == SNMPv3_MP_OK) {
455       if ((pdu->get_type() == sNMP_PDU_RESPONSE) &&
456           ((int)pdu->get_maxsize_scopedpdu() < pdu->get_asn1_length())) {
457
458         LOG_BEGIN(ERROR_LOG | 1);
459         LOG("SNMPMessage: *BUG*: Serialized response pdu is too big (len) (max)");
460         LOG(pdu->get_asn1_length());
461         LOG(pdu->get_maxsize_scopedpdu());
462         LOG_END;
463
464         // prevention of SNMP++ Enterprise Oid death
465         if ( enterprise.len() >0) {
466           raw_pdu->enterprise = 0;
467           raw_pdu->enterprise_length=0;
468         }
469         snmp_free_pdu( raw_pdu);
470         return SNMP_ERROR_TOO_BIG;
471       }
472     }
473   }
474   else
475 #endif
476     status = snmp_build( raw_pdu, databuff, (int *) &bufflen, version,
477                          community.data(), (int) community.len());
478
479   LOG_BEGIN(DEBUG_LOG | 4);
480   LOG("SNMPMessage: return value for build message");
481   LOG(status);
482   LOG_END;
483
484   if ((status != 0)
485 #ifdef _SNMPv3
486       && ((version != version3) || (status != SNMPv3_MP_OK))
487 #endif
488       ) {
489     valid_flag = false;
490     // prevention of SNMP++ Enterprise Oid death
491     if ( enterprise.len() >0) {
492       raw_pdu->enterprise = 0;
493       raw_pdu->enterprise_length=0;
494     }
495     snmp_free_pdu( raw_pdu);
496 #ifdef _SNMPv3
497     if (version == version3)
498       return status;
499     else
500 #endif
501       // NOTE: This is an assumption - in most cases during normal
502       // operation the reason is a tooBig - another could be a
503       // damaged variable binding.
504       return SNMP_ERROR_TOO_BIG;
505   }
506   valid_flag = true;
507
508   // prevention of SNMP++ Enterprise Oid death
509   if ( enterprise.len() >0) {
510     raw_pdu->enterprise = 0;
511     raw_pdu->enterprise_length=0;
512   }
513
514   snmp_free_pdu( raw_pdu);
515
516   return SNMP_CLASS_SUCCESS;
517 }
518
519 // load up a SnmpMessage
520 int SnmpMessage::load( unsigned char *data,
521                        unsigned long len)
522 {
523   bufflen = MAX_SNMP_PACKET;
524   valid_flag = false;
525
526   if (len <= MAX_SNMP_PACKET)
527   {
528     memcpy( (unsigned char *) databuff, (unsigned char *) data,
529             (unsigned int) len);
530     bufflen = len;
531     valid_flag = true;
532   }
533   else
534     return SNMP_ERROR_WRONG_LENGTH;
535
536   return SNMP_CLASS_SUCCESS;
537 }
538
539 // unload the data into SNMP++ objects
540 int SnmpMessage::unload(Pdu &pdu,                 // Pdu object
541                         OctetStr &community,      // community object
542                         snmp_version &version,    // SNMP version #
543                         OctetStr *engine_id,      // optional v3
544                         OctetStr *security_name,  // optional v3
545                         long int *security_model,
546                         UdpAddress *from_addr,
547                         Snmp *snmp_session)
548 {
549   pdu.clear();
550
551   if (!valid_flag)
552     return SNMP_CLASS_INVALID;
553
554   snmp_pdu *raw_pdu;
555   raw_pdu = snmp_pdu_create(0); // do a "snmp_free_pdu( raw_pdu)" before return
556
557   int status;
558
559 #ifdef _SNMPv3
560   OctetStr context_engine_id;
561   OctetStr context_name;
562   long int security_level = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
563
564   if ((security_model) && (security_name) && (engine_id) && (snmp_session)) {
565     status = v3MP::I->snmp_parse(snmp_session, raw_pdu,
566                          databuff, (int)bufflen, *engine_id,
567                          *security_name, context_engine_id, context_name,
568                          security_level, *security_model, version, *from_addr);
569     if (status != SNMPv3_MP_OK) {
570       pdu.set_request_id( raw_pdu->reqid);
571       pdu.set_type( raw_pdu->command);
572       snmp_free_pdu( raw_pdu);
573       return status;
574     }
575     pdu.set_context_engine_id(context_engine_id);
576     pdu.set_context_name(context_name);
577     pdu.set_security_level(security_level);
578     pdu.set_message_id(raw_pdu->msgid);
579     pdu.set_maxsize_scopedpdu(raw_pdu->maxsize_scopedpdu);
580   }
581   else {
582 #endif
583     unsigned char community_name[MAX_LEN_COMMUNITY + 1];
584     int           community_len = MAX_LEN_COMMUNITY + 1;
585
586     status = snmp_parse(raw_pdu, databuff, (int) bufflen,
587                         community_name, community_len, version);
588     if (status != SNMP_CLASS_SUCCESS) {
589       snmp_free_pdu(raw_pdu);
590       return status;
591     }
592     community.set_data( community_name, community_len);
593
594 #ifdef _SNMPv3
595   }
596 #endif
597   // load up the SNMP++ variables
598   pdu.set_request_id(raw_pdu->reqid);
599   pdu.set_error_status((int) raw_pdu->errstat);
600   pdu.set_error_index((int) raw_pdu->errindex);
601   pdu.set_type( raw_pdu->command);
602
603   // deal with traps a little different
604   if ( raw_pdu->command == sNMP_PDU_V1TRAP) {
605     // timestamp
606     TimeTicks timestamp;
607     timestamp = raw_pdu->time;
608     pdu.set_notify_timestamp( timestamp);
609
610     // set the agent address
611     IpAddress agent_addr(inet_ntoa(raw_pdu->agent_addr.sin_addr));
612     if (agent_addr != "0.0.0.0")
613     {
614       pdu.set_v1_trap_address(agent_addr);
615
616       LOG_BEGIN(DEBUG_LOG | 4);
617       LOG("SNMPMessage: Trap address of received v1 trap");
618       LOG(agent_addr.get_printable());
619       LOG_END;
620     }
621
622     // set enterprise, notifyid
623     Oid enterprise;
624
625     if (raw_pdu->enterprise_length >0) {
626       for (int i=0; i< raw_pdu->enterprise_length; i++) {
627         enterprise += (int) (raw_pdu->enterprise[i]);
628       }
629       pdu.set_notify_enterprise(enterprise);
630     }
631     switch (raw_pdu->trap_type) {
632     case 0:
633       pdu.set_notify_id(coldStart);
634       break;
635
636     case 1:
637       pdu.set_notify_id(warmStart);
638       break;
639
640     case 2:
641       pdu.set_notify_id(linkDown);
642       break;
643
644     case 3:
645       pdu.set_notify_id(linkUp);
646       break;
647
648     case 4:
649       pdu.set_notify_id(authenticationFailure);
650       break;
651
652     case 5:
653       pdu.set_notify_id(egpNeighborLoss);
654       break;
655
656     case 6: { // enterprise specific
657       // base id + specific #
658       Oid eOid = enterprise;
659       eOid += 0ul;
660       eOid += raw_pdu->specific_type;
661       pdu.set_notify_id( eOid);
662       break;
663       }
664     default:
665       {
666         LOG_BEGIN(WARNING_LOG | 3);
667         LOG("SNMPMessage: Received trap with illegal trap type");
668         LOG(raw_pdu->trap_type);
669         LOG_END;
670       }
671     }
672   }
673
674   // vbs
675   Vb tempvb;
676   Oid tempoid;
677   struct   variable_list *vp;
678   int vb_nr = 1;
679
680   for(vp = raw_pdu->variables; vp; vp = vp->next_variable, vb_nr++) {
681
682     // extract the oid portion
683     tempoid.set_data( (unsigned long *)vp->name,
684                       ( unsigned int) vp->name_length);
685     tempvb.set_oid( tempoid);
686
687     // extract the value portion
688     switch(vp->type){
689
690       // octet string
691     case sNMP_SYNTAX_OCTETS:
692       {
693         OctetStr octets( (unsigned char *) vp->val.string,
694                          (unsigned long) vp->val_len);
695         tempvb.set_value( octets);
696       }
697       break;
698     case sNMP_SYNTAX_OPAQUE:
699       {
700         OpaqueStr octets( (unsigned char *) vp->val.string,
701                           (unsigned long) vp->val_len);
702         tempvb.set_value( octets);
703       }
704       break;
705
706       // object id
707     case sNMP_SYNTAX_OID:
708       {
709         Oid oid( (unsigned long*) vp->val.objid,
710                  (int) vp->val_len);
711         tempvb.set_value( oid);
712         if ((vb_nr == 2) &&
713             ((raw_pdu->command == sNMP_PDU_TRAP) ||
714              (raw_pdu->command == sNMP_PDU_INFORM)) &&
715             (tempoid == SNMP_MSG_OID_TRAPID))
716         {
717           // set notify_id
718           pdu.set_notify_id(oid);
719           continue; // don't add vb to pdu
720         }
721       }
722       break;
723
724       // timeticks
725     case sNMP_SYNTAX_TIMETICKS:
726       {
727         TimeTicks timeticks( (unsigned long) *(vp->val.integer));
728         tempvb.set_value( timeticks);
729         if ((vb_nr == 1) &&
730             ((raw_pdu->command == sNMP_PDU_TRAP) ||
731              (raw_pdu->command == sNMP_PDU_INFORM)) &&
732             (tempoid == SNMP_MSG_OID_SYSUPTIME))
733         {
734           // set notify_timestamp
735           pdu.set_notify_timestamp( timeticks);
736           continue; // don't add vb to pdu
737         }
738       }
739       break;
740
741       // 32 bit counter
742     case sNMP_SYNTAX_CNTR32:
743       {
744         Counter32 counter32( (unsigned long) *(vp->val.integer));
745         tempvb.set_value( counter32);
746       }
747       break;
748
749       // 32 bit gauge
750     case sNMP_SYNTAX_GAUGE32:
751       {
752         Gauge32 gauge32( (unsigned long) *(vp->val.integer));
753         tempvb.set_value( gauge32);
754       }
755       break;
756
757       // ip address
758     case sNMP_SYNTAX_IPADDR:
759       {
760         char buffer[42];
761
762         if (vp->val_len == 16)
763           sprintf( buffer, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
764                    "%02x%02x:%02x%02x:%02x%02x:%02x%02x",
765                    vp->val.string[ 0], vp->val.string[ 1], vp->val.string[ 2],
766                    vp->val.string[ 3], vp->val.string[ 4], vp->val.string[ 5],
767                    vp->val.string[ 6], vp->val.string[ 7], vp->val.string[ 8],
768                    vp->val.string[ 9], vp->val.string[10], vp->val.string[11],
769                    vp->val.string[12], vp->val.string[13], vp->val.string[14],
770                    vp->val.string[15]);
771         else
772           sprintf( buffer,"%d.%d.%d.%d",
773                    vp->val.string[0], vp->val.string[1],
774                    vp->val.string[2], vp->val.string[3]);
775         IpAddress ipaddress( buffer);
776         tempvb.set_value( ipaddress);
777       }
778       break;
779
780       // 32 bit integer
781     case sNMP_SYNTAX_INT:
782       {
783         SnmpInt32 int32( (long) *(vp->val.integer));
784         tempvb.set_value( int32);
785       }
786       break;
787
788       // 32 bit unsigned integer
789 /* Not distinguishable from Gauge32
790     case sNMP_SYNTAX_UINT32:
791       {
792         SnmpUInt32 uint32( (unsigned long) *(vp->val.integer));
793         tempvb.set_value( uint32);
794       }
795       break;
796 */
797       // v2 counter 64's
798     case sNMP_SYNTAX_CNTR64:
799       { // Frank Fock (was empty before)
800         Counter64 c64(((counter64*)vp->val.counter64)->high,
801                       ((counter64*)vp->val.counter64)->low);
802         tempvb.set_value( c64);
803         break;
804       }
805     case sNMP_SYNTAX_NULL:
806             tempvb.set_null();
807             break;
808         
809             // v2 vb exceptions
810     case sNMP_SYNTAX_NOSUCHOBJECT:
811     case sNMP_SYNTAX_NOSUCHINSTANCE:
812     case sNMP_SYNTAX_ENDOFMIBVIEW:
813       tempvb.set_exception_status(vp->type);
814       break;
815
816     default:
817       tempvb.set_null();
818
819     } // end switch
820
821     // append the vb to the pdu
822     pdu += tempvb;
823   }
824
825   snmp_free_pdu( raw_pdu);
826
827   return SNMP_CLASS_SUCCESS;
828 }
829
830 #ifdef SNMP_PP_NAMESPACE
831 }; // end of namespace Snmp_pp
832 #endif