php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #53594
Patch patch-ext-snmp-tests revision 2011-01-05 18:00 UTC by lytboris at gmail dot com
revision 2010-12-29 16:50 UTC by lytboris at gmail dot com
revision 2010-12-22 18:53 UTC by lytboris at gmail dot com
Patch patch-ext-snmp-src revision 2011-01-05 17:59 UTC by lytboris at gmail dot com
revision 2010-12-29 16:50 UTC by lytboris at gmail dot com
Patch patch-ext-snmp-trunk revision 2010-12-23 06:18 UTC by lytboris at gmail dot com
revision 2010-12-23 06:16 UTC by lytboris at gmail dot com
Patch php-ext-snmp-source revision 2010-12-22 18:52 UTC by lytboris at gmail dot com

Patch patch-ext-snmp-src for SNMP related Bug #53594

Patch version 2011-01-05 17:59 UTC

Return to Bug #53594 | Download this patch
This patch renders other patches obsolete

Obsolete patches:

Patch Revisions: 2011-01-05 17:59 UTC | 2010-12-29 16:50 UTC

Developer: lytboris@gmail.com


 diff -urN -x .svn ext/snmp/php_snmp.h ext/snmp/php_snmp.h
 --- ext/snmp/php_snmp.h	2010-12-29 19:40:21.000000000 +0300
 +++ ext/snmp/php_snmp.h	2010-12-29 17:59:40.000000000 +0300
 @@ -42,24 +42,34 @@
  PHP_MSHUTDOWN_FUNCTION(snmp);
  PHP_MINFO_FUNCTION(snmp);
 diff -ruN trunk/ext/snmp/CREDITS snmp-new/ext/snmp/CREDITS
 --- trunk/ext/snmp/CREDITS	2007-09-26 19:44:16.000000000 +0400
 +++ snmp-new/ext/snmp/CREDITS	2011-01-05 18:47:48.000000000 +0300
 @@ -1,2 +1,2 @@
  SNMP
 -Rasmus Lerdorf, Harrie Hazewinkel, Mike Jackson, Steven Lawrance, Johann Hanne
 +Rasmus Lerdorf, Harrie Hazewinkel, Mike Jackson, Steven Lawrance, Johann Hanne, Boris Lytochkin
 diff -ruN trunk/ext/snmp/php_snmp.h snmp-new/ext/snmp/php_snmp.h
 --- trunk/ext/snmp/php_snmp.h	2011-01-01 05:17:06.058523000 +0300
 +++ snmp-new/ext/snmp/php_snmp.h	2011-01-05 18:40:24.000000000 +0300
 @@ -17,6 +17,7 @@
    |          Steven Lawrance <slawrance@technologist.com>                |
    |          Harrie Hazewinkel <harrie@lisanza.net>                      |
    |          Johann Hanne <jonny@nurfuerspam.de>                         |
 +  |          Boris Lytockin <lytboris@gmail.com>                         |
    +----------------------------------------------------------------------+
  */
  
 @@ -25,6 +26,8 @@
  #ifndef PHP_SNMP_H
  #define PHP_SNMP_H
   
 +PHP_FUNCTION(snmp_session_open);
 +PHP_FUNCTION(snmp_session_close);
 +PHP_FUNCTION(snmp_session_set_security);
 +#define PHP_SNMP_VERSION "0.1"
  +
  PHP_FUNCTION(snmpget);
 +PHP_FUNCTION(snmprealget);
  #if HAVE_SNMP
  
  #ifndef DLEXPORT
 @@ -46,11 +49,11 @@
   PHP_FUNCTION(snmpgetnext);
 +PHP_FUNCTION(snmprealgetnext);
   PHP_FUNCTION(snmpwalk);
   PHP_FUNCTION(snmprealwalk);
  +PHP_FUNCTION(snmpset);
   PHP_FUNCTION(snmp_get_quick_print);


   PHP_FUNCTION(snmp_set_oid_output_format);
  -PHP_FUNCTION(snmpset);
   
   PHP_FUNCTION(snmp2_get);
 +PHP_FUNCTION(snmp2_real_get);
   PHP_FUNCTION(snmp2_getnext);
 +PHP_FUNCTION(snmp2_real_getnext);
  PHP_FUNCTION(snmp2_walk);
  PHP_FUNCTION(snmp2_real_walk);
  PHP_FUNCTION(snmp2_set);
 @@ -69,6 +72,35 @@
  
  PHP_FUNCTION(snmp_read_mib);
  
 +PHP_METHOD(SNMP, open);
 +PHP_METHOD(SNMP, set_security);
 +PHP_METHOD(SNMP, close);
 +PHP_METHOD(SNMP, get);
 +PHP_METHOD(SNMP, getnext);
 +PHP_METHOD(SNMP, walk);
 +PHP_METHOD(SNMP, set);
 +
 +typedef struct _php_snmp_object {
 +      zend_object zo;
 +      struct snmp_session *session;
 +      int valueretrieval;
 +      int quick_print;
 +#ifdef HAVE_NET_SNMP
 +      int enum_print;
 +      int oid_output_format;
 +#endif
 +} php_snmp_object;
 +
 +
 +typedef int (*php_snmp_read_t)(php_snmp_object *snmp_object, zval **retval TSRMLS_DC);
 +typedef int (*php_snmp_write_t)(php_snmp_object *snmp_object, zval *newval TSRMLS_DC);
 +
 +typedef struct _ptp_snmp_prop_handler {
 +      const char *name;
 +      size_t name_length;
 +      php_snmp_read_t read_func;
 +      php_snmp_write_t write_func;
 +} php_snmp_prop_handler;
  
  ZEND_BEGIN_MODULE_GLOBALS(snmp)
        int valueretrieval;
 diff -ruN trunk/ext/snmp/snmp.c snmp-new/ext/snmp/snmp.c
 --- trunk/ext/snmp/snmp.c	2011-01-01 05:17:06.058523000 +0300
 +++ snmp-new/ext/snmp/snmp.c	2011-01-05 20:05:46.000000000 +0300
 @@ -17,6 +17,7 @@
     |          Steven Lawrance <slawrance@technologist.com>                |
     |          Harrie Hazewinkel <harrie@lisanza.net>                      |
     |          Johann Hanne <jonny@nurfuerspam.de>                         |
 +   |          Boris Lytockin <lytboris@gmail.com>                         |
     +----------------------------------------------------------------------+
   */
  
 @@ -30,6 +31,8 @@
  #include "ext/standard/info.h"
  #include "php_snmp.h"
  
 +#include "zend_exceptions.h"
 +
  #if HAVE_SNMP
   
  PHP_FUNCTION(snmp3_get);
 +PHP_FUNCTION(snmp3_real_get);
  PHP_FUNCTION(snmp3_getnext);
 +PHP_FUNCTION(snmp3_real_getnext);
  PHP_FUNCTION(snmp3_walk);
  PHP_FUNCTION(snmp3_real_walk);
  PHP_FUNCTION(snmp3_set);
 diff -urN -x .svn ext/snmp/snmp.c ext/snmp/snmp.c
 --- ext/snmp/snmp.c	2010-12-29 19:40:21.000000000 +0300
 +++ ext/snmp/snmp.c	2010-12-29 19:28:06.000000000 +0300
 @@ -97,6 +98,20 @@
  #include <sys/types.h>
 @@ -97,6 +100,23 @@
    */
   #define OIDSIZE(p) (sizeof(p)/sizeof(oid))
   
  +/* Another ugly macros, since UCD-SNMP has no snprint_* */
Line 53 (now 107), was 90 lines, now 71 lines

  +#define SNMP_SNPRINT_VALUE(dst, dstlen, srcname, srcnamelen, src) (sprint_value((dst), (srcname), (srcnamelen), (src)))
  +#endif
  +
  +#if PHP_VERSION_ID < 50300
 +#define Z_ADDREF_P(pz) pz->refcount++
  +#define Z_ISREF_PP(oid) (PZVAL_IS_REF(*(oid)))
 +#define Z_REFCOUNT_P(pz) pz->refcount
 +#define Z_SET_REFCOUNT_P(pz, rc) pz->refcount = rc
  +#define zend_parse_parameters_none() zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")
  +#endif
  +
   /* For really old ucd-snmp versions.. */
   #ifndef HAVE_SNMP_PARSE_OID
   #define snmp_parse_oid read_objid
 @@ -106,13 +121,43 @@
 @@ -106,13 +126,51 @@
   #define SNMP_VALUE_PLAIN	1
   #define SNMP_VALUE_OBJECT	2
   
  +typedef struct snmp_session php_snmp_session;
  +#define PHP_SNMP_SESSION_RES_NAME "SNMP session"
 +
 +#define PHP_SNMP_SESSION_FROM_OBJECT(session, object) \
 +	{ \
 +		php_snmp_object *snmp_object; \
 +		snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC); \
 +		session = snmp_object->session; \
 +		if (!session) { \
 +			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized SNMP object"); \
 +			RETURN_FALSE; \
 +		} \
 +	}
 +
 +#define PHP_SNMP_ADD_PROPERTIES(a, b) \
 +{ \
 +	int i = 0; \
 +	while (b[i].name != NULL) { \
 +		php_snmp_add_property((a), (b)[i].name, (b)[i].name_length, \
 +							(php_snmp_read_t)(b)[i].read_func, (php_snmp_write_t)(b)[i].write_func TSRMLS_CC); \
 +		i++; \
 +	} \
 +}
 +
 +
  +
   ZEND_DECLARE_MODULE_GLOBALS(snmp)
   static PHP_GINIT_FUNCTION(snmp);
  
  
   /* constant - can be shared among threads */
   static oid objid_mib[] = {1, 3, 6, 1, 2, 1};
   
  +static int le_snmp_session;
  +
  /* {{{ arginfo */
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_session_open, 0, 0, 3)
 +	ZEND_ARG_INFO(0, version)
 +	ZEND_ARG_INFO(0, host)
 +	ZEND_ARG_INFO(0, community)
 +	ZEND_ARG_INFO(0, timeout)
 +	ZEND_ARG_INFO(0, retries)
 +ZEND_END_ARG_INFO()
 +
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_session_close, 0, 0, 1)
 +	ZEND_ARG_INFO(0, session)
 +ZEND_END_ARG_INFO()
 +
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_session_set_security, 0, 0, 8)
 +	ZEND_ARG_INFO(0, session)
 +	ZEND_ARG_INFO(0, sec_level)
 +	ZEND_ARG_INFO(0, auth_protocol)
 +	ZEND_ARG_INFO(0, auth_passphrase)
 +	ZEND_ARG_INFO(0, priv_protocol)
 +	ZEND_ARG_INFO(0, priv_passphrase)
 +	ZEND_ARG_INFO(0, contextName)
 +	ZEND_ARG_INFO(0, contextEngineID)
 +	ZEND_ARG_INFO(0, )
 +ZEND_END_ARG_INFO()
 +
 +/*
 +/* Handlers */
 +static zend_object_handlers php_snmp_object_handlers;
 +
 +/* Class entries */
 +zend_class_entry *php_snmp_class_entry;
 +
 +/* Class object properties */
 +static HashTable php_snmp_properties;
 +
  /* {{{ arginfo */
 +
   ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpget, 0, 0, 3)
   	ZEND_ARG_INFO(0, host)
   	ZEND_ARG_INFO(0, community)
 @@ -121,6 +166,14 @@
  	ZEND_ARG_INFO(0, retries)
  ZEND_END_ARG_INFO()
  
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmprealget, 0, 0, 3)
 +	ZEND_ARG_INFO(0, host)
 +	ZEND_ARG_INFO(0, community)
 +	ZEND_ARG_INFO(0, object_id)
 +	ZEND_ARG_INFO(0, timeout)
 +	ZEND_ARG_INFO(0, retries)
 +ZEND_END_ARG_INFO()
 +
  ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpgetnext, 0, 0, 3)
  	ZEND_ARG_INFO(0, host)
  	ZEND_ARG_INFO(0, community)
 @@ -129,6 +182,14 @@
  	ZEND_ARG_INFO(0, retries)
  ZEND_END_ARG_INFO()
  
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmprealgetnext, 0, 0, 3)
 +	ZEND_ARG_INFO(0, host)
 +	ZEND_ARG_INFO(0, community)
 +	ZEND_ARG_INFO(0, object_id)
 +	ZEND_ARG_INFO(0, timeout)
 +	ZEND_ARG_INFO(0, retries)
 +ZEND_END_ARG_INFO()
 +
  ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpwalk, 0, 0, 3)
  	ZEND_ARG_INFO(0, host)
  	ZEND_ARG_INFO(0, community)
 @@ -145,6 +206,17 @@
 @@ -145,6 +203,17 @@
   	ZEND_ARG_INFO(0, retries)
   ZEND_END_ARG_INFO()
   
  +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpset, 0, 0, 5)
Line 147 (now 182), was 95 lines, now 91 lines

  +	ZEND_ARG_INFO(0, value)
  +	ZEND_ARG_INFO(0, timeout)
  +	ZEND_ARG_INFO(0, retries)
  +ZEND_END_ARG_INFO()
 +*/
 +
  +
   ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_get_quick_print, 0, 0, 1)
   	ZEND_ARG_INFO(0, d)
   ZEND_END_ARG_INFO()
 @@ -163,17 +235,15 @@
 @@ -163,16 +232,6 @@
   ZEND_END_ARG_INFO()
   #endif
   
  -ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpset, 0, 0, 5)
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_get, 0, 0, 3)
  	ZEND_ARG_INFO(0, host)
  	ZEND_ARG_INFO(0, community)
  	ZEND_ARG_INFO(0, object_id)
 -	ZEND_ARG_INFO(0, host)
 -	ZEND_ARG_INFO(0, community)
 -	ZEND_ARG_INFO(0, object_id)
  -	ZEND_ARG_INFO(0, type)
  -	ZEND_ARG_INFO(0, value)
  	ZEND_ARG_INFO(0, timeout)
  	ZEND_ARG_INFO(0, retries)
  ZEND_END_ARG_INFO()
  
 -ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_get, 0, 0, 3)
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_real_get, 0, 0, 3)
  	ZEND_ARG_INFO(0, host)
  	ZEND_ARG_INFO(0, community)
  	ZEND_ARG_INFO(0, object_id)
 @@ -189,6 +259,14 @@
  	ZEND_ARG_INFO(0, retries)
  ZEND_END_ARG_INFO()
  
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_real_getnext, 0, 0, 3)
 +	ZEND_ARG_INFO(0, host)
 +	ZEND_ARG_INFO(0, community)
 +	ZEND_ARG_INFO(0, object_id)
 +	ZEND_ARG_INFO(0, timeout)
 +	ZEND_ARG_INFO(0, retries)
 +ZEND_END_ARG_INFO()
 +
  ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_walk, 0, 0, 3)
 -	ZEND_ARG_INFO(0, timeout)
 -	ZEND_ARG_INFO(0, retries)
 -ZEND_END_ARG_INFO()
 -
  ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_get, 0, 0, 3)
   	ZEND_ARG_INFO(0, host)
   	ZEND_ARG_INFO(0, community)
 @@ -215,12 +293,20 @@
 @@ -215,11 +274,6 @@
   	ZEND_ARG_INFO(0, retries)
   ZEND_END_ARG_INFO()
   
  -ZEND_BEGIN_ARG_INFO_EX(arginfo_php_snmpv3, 0, 0, 2)
  -	ZEND_ARG_INFO(0, s)
  -	ZEND_ARG_INFO(0, st)
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_get, 0, 0, 8)
 +	ZEND_ARG_INFO(0, host)
 +	ZEND_ARG_INFO(0, sec_name)
 +	ZEND_ARG_INFO(0, sec_level)
 +	ZEND_ARG_INFO(0, auth_protocol)
 +	ZEND_ARG_INFO(0, auth_passphrase)
 +	ZEND_ARG_INFO(0, priv_protocol)
 +	ZEND_ARG_INFO(0, priv_passphrase)
 +	ZEND_ARG_INFO(0, object_id)
 +	ZEND_ARG_INFO(0, timeout)
 +	ZEND_ARG_INFO(0, retries)
  ZEND_END_ARG_INFO()
  
 -ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_get, 0, 0, 8)
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_real_get, 0, 0, 8)
 -ZEND_END_ARG_INFO()
 -
  ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_get, 0, 0, 8)
   	ZEND_ARG_INFO(0, host)
   	ZEND_ARG_INFO(0, sec_name)
  	ZEND_ARG_INFO(0, sec_level)
 @@ -246,6 +332,19 @@
  	ZEND_ARG_INFO(0, retries)
 @@ -297,16 +351,76 @@
  ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_read_mib, 0, 0, 1)
  	ZEND_ARG_INFO(0, filename)
   ZEND_END_ARG_INFO()
  
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_real_getnext, 0, 0, 8)
 +
 +/* OO arginfo */
 +
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_open, 0, 0, 3)
 +	ZEND_ARG_INFO(0, version)
  +	ZEND_ARG_INFO(0, host)
 +	ZEND_ARG_INFO(0, sec_name)
 +	ZEND_ARG_INFO(0, community)
 +	ZEND_ARG_INFO(0, timeout)
 +	ZEND_ARG_INFO(0, retries)
 +ZEND_END_ARG_INFO()
 +
 +ZEND_BEGIN_ARG_INFO(arginfo_snmp_void, 0)
 +ZEND_END_ARG_INFO()
 +
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_security, 0, 0, 8)
 +	ZEND_ARG_INFO(0, session)
  +	ZEND_ARG_INFO(0, sec_level)
  +	ZEND_ARG_INFO(0, auth_protocol)
  +	ZEND_ARG_INFO(0, auth_passphrase)
  +	ZEND_ARG_INFO(0, priv_protocol)
  +	ZEND_ARG_INFO(0, priv_passphrase)
 +	ZEND_ARG_INFO(0, contextName)
 +	ZEND_ARG_INFO(0, contextEngineID)
 +	ZEND_ARG_INFO(0, )
 +ZEND_END_ARG_INFO()
 +
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_get, 0, 0, 1)
 +	ZEND_ARG_INFO(0, object_id)
 +ZEND_END_ARG_INFO()
 +
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_walk, 0, 0, 3)
 +	ZEND_ARG_INFO(0, object_id)
 +	ZEND_ARG_INFO(0, non_repeaters)
 +	ZEND_ARG_INFO(0, max_repetitions)
 +ZEND_END_ARG_INFO()
 +
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set, 0, 0, 3)
  +	ZEND_ARG_INFO(0, object_id)
 +	ZEND_ARG_INFO(0, timeout)
 +	ZEND_ARG_INFO(0, retries)
 +ZEND_END_ARG_INFO()
 +	ZEND_ARG_INFO(0, type)
 +	ZEND_ARG_INFO(0, value)
 +ZEND_END_ARG_INFO()
  +
  ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_walk, 0, 0, 8)
  	ZEND_ARG_INFO(0, host)
  	ZEND_ARG_INFO(0, sec_name)
 @@ -299,14 +398,34 @@
  ZEND_END_ARG_INFO()
 +ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_class_set_quick_print, 0, 0, 1)
 +	ZEND_ARG_INFO(0, quick_print)
 +ZEND_END_ARG_INFO()
   /* }}} */
   
  +typedef struct _snmpobjarg {
  +	char *oid;
Line 258 (now 289), was 43 lines, now 34 lines

  -	PHP_FE(snmpgetnext, 					arginfo_snmpgetnext)
  -	PHP_FE(snmpwalk, 						arginfo_snmpwalk)
  -	PHP_FE(snmprealwalk, 					arginfo_snmprealwalk)
  -	PHP_FALIAS(snmpwalkoid, snmprealwalk, 	arginfo_snmprealwalk)
 +	PHP_FE(snmp_session_open,			arginfo_snmp_session_open)
 +	PHP_FE(snmp_session_close,			arginfo_snmp_session_close)
 +	PHP_FE(snmp_session_set_security,		arginfo_snmp_session_set_security)
 +	PHP_FE(snmpget,					0/*arginfo_snmpget*/)
 +	PHP_FE(snmprealget,				0/*arginfo_snmprealget*/)
 +	PHP_FE(snmpgetnext, 				0/*arginfo_snmpgetnext*/)
 +	PHP_FE(snmprealgetnext, 			0/*arginfo_snmprealgetnext*/)
 +	PHP_FE(snmpwalk, 				0/*arginfo_snmpwalk*/)
 +	PHP_FE(snmprealwalk, 				0/*arginfo_snmprealwalk*/)
 +	PHP_FALIAS(snmpwalkoid, snmprealwalk, 		0/*arginfo_snmprealwalk*/)
 +	PHP_FE(snmpset, 				0/*arginfo_snmpset*/)
 +	PHP_FE(snmpget,					arginfo_snmpget)
 +	PHP_FE(snmpgetnext, 				arginfo_snmpgetnext)
 +	PHP_FE(snmpwalk, 				arginfo_snmpwalk)
 +	PHP_FE(snmprealwalk, 				arginfo_snmprealwalk)
 +	PHP_FALIAS(snmpwalkoid, snmprealwalk, 		arginfo_snmprealwalk)
 +	PHP_FE(snmpset, 				arginfo_snmpset)
   	PHP_FE(snmp_get_quick_print, 			arginfo_snmp_get_quick_print)
   	PHP_FE(snmp_set_quick_print, 			arginfo_snmp_set_quick_print)
   #ifdef HAVE_NET_SNMP
 @@ -314,32 +433,40 @@
 @@ -314,52 +428,36 @@
   	PHP_FE(snmp_set_oid_output_format, 		arginfo_snmp_set_oid_output_format)
   	PHP_FALIAS(snmp_set_oid_numeric_print, snmp_set_oid_output_format, arginfo_snmp_set_oid_output_format)
   #endif
  -	PHP_FE(snmpset, 				arginfo_snmpset)
   
   	PHP_FE(snmp2_get, 				arginfo_snmp2_get)
  -	PHP_FE(snmp2_getnext, 			arginfo_snmp2_getnext)
 +	PHP_FE(snmp2_real_get, 				arginfo_snmp2_real_get)
  +	PHP_FE(snmp2_getnext, 				arginfo_snmp2_getnext)
 +	PHP_FE(snmp2_real_getnext, 			arginfo_snmp2_real_getnext)
   	PHP_FE(snmp2_walk, 				arginfo_snmp2_walk)
  -	PHP_FE(snmp2_real_walk, 		arginfo_snmp2_real_walk)
  +	PHP_FE(snmp2_real_walk, 			arginfo_snmp2_real_walk)
   	PHP_FE(snmp2_set, 				arginfo_snmp2_set)
   
   	PHP_FE(snmp3_get, 				arginfo_snmp3_get)
  -	PHP_FE(snmp3_getnext, 			arginfo_snmp3_getnext)
 +	PHP_FE(snmp3_real_get, 				arginfo_snmp3_real_get)
  +	PHP_FE(snmp3_getnext, 				arginfo_snmp3_getnext)
 +	PHP_FE(snmp3_real_getnext,			arginfo_snmp3_real_getnext)
   	PHP_FE(snmp3_walk, 				arginfo_snmp3_walk)
  -	PHP_FE(snmp3_real_walk, 		arginfo_snmp3_real_walk)
  +	PHP_FE(snmp3_real_walk, 			arginfo_snmp3_real_walk)
   	PHP_FE(snmp3_set, 				arginfo_snmp3_set)


  -#define SNMP_CMD_GETNEXT	2
  -#define SNMP_CMD_WALK		3
  -#define SNMP_CMD_REALWALK	4
  -#define SNMP_CMD_SET		11
 -
 -/* {{{ snmp_module_entry
 - */
 -zend_module_entry snmp_module_entry = {
 -	STANDARD_MODULE_HEADER,
 -	"snmp",
 -	snmp_functions,
 -	PHP_MINIT(snmp),
 -	PHP_MSHUTDOWN(snmp),
 -	NULL,
 -	NULL,
 -	PHP_MINFO(snmp),
 -	NO_VERSION_YET,
 -	PHP_MODULE_GLOBALS(snmp),
 -	PHP_GINIT(snmp),
 -	NULL,
 -	NULL,
 -	STANDARD_MODULE_PROPERTIES_EX
 -};
 -/* }}} */
  +/* query an agent with GET method */
  +#define SNMP_CMD_GET		(1<<0)
  +/* query an agent with GETNEXT method */
  +#define SNMP_CMD_GETNEXT	(1<<1)


  +#define SNMP_CMD_SET		(1<<2)
  +/* walk the mib */
  +#define SNMP_CMD_WALK		(1<<3)
  +/* force oid,value output */
 +#define SNMP_ASSOC_OUTPUT	(1<<7)
 +#define SNMP_NUMERIC_KEYS	(1<<7)
   
  /* {{{ snmp_module_entry
   */
 @@ -375,10 +502,30 @@
  #ifdef COMPILE_DL_SNMP
  ZEND_GET_MODULE(snmp)
 @@ -375,86 +473,83 @@
   }
   /* }}} */
  
 +static void netsnmp_session_free(php_snmp_session *session)
 +{
 +	if (session) {
 +		if (session->peername) {
 +			efree(session->peername);
  
 -/* {{{ PHP_MINIT_FUNCTION
 - */
 -PHP_MINIT_FUNCTION(snmp)
 +static void netsnmp_session_free(php_snmp_session **session)
  {
 -	init_snmp("snmpapp");
 -
 -#ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
 -	/* Prevent update of the snmpapp.conf file */
 -	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
 -#endif
 +	if (*session) {
 +		if ((*session)->peername) {
 +			efree((*session)->peername);
  +		}
 +		efree(session);
 +		efree(*session);
 +		*session = NULL;
  +	}
 +}
 +
 +}
  
 -#ifdef HAVE_NET_SNMP
 -	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_FULL", NETSNMP_OID_OUTPUT_FULL, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NUMERIC", NETSNMP_OID_OUTPUT_NUMERIC, CONST_CS | CONST_PERSISTENT);
 -#endif
  +static void php_snmp_session_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  +{
  +	php_snmp_session *session = (php_snmp_session *)rsrc->ptr;
 +	netsnmp_session_free(session);
 +	netsnmp_session_free(&session);
  +}
 +
  /* {{{ PHP_MINIT_FUNCTION
   */
  PHP_MINIT_FUNCTION(snmp)
  {
 +	netsnmp_log_handler *logh;
 +
 +	le_snmp_session = zend_register_list_destructors_ex(php_snmp_session_destructor, NULL, PHP_SNMP_SESSION_RES_NAME, module_number);
 +
  	init_snmp("snmpapp");
  
  #ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
 @@ -386,6 +533,13 @@
  	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
  #endif
  
 +	/* Disable logging, use exit status'es and related variabled to detect errors */
 +	shutdown_snmp_logging();
 +	logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_NONE, LOG_ERR);
 +	if (logh) {
 +		logh->pri_max = LOG_ERR;
 +	}
 +
  #ifdef HAVE_NET_SNMP
  	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_FULL", NETSNMP_OID_OUTPUT_FULL, CONST_CS | CONST_PERSISTENT);
  	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NUMERIC", NETSNMP_OID_OUTPUT_NUMERIC, CONST_CS | CONST_PERSISTENT);
 @@ -408,6 +562,9 @@
  	REGISTER_LONG_CONSTANT("SNMP_INTEGER", ASN_INTEGER, CONST_CS | CONST_PERSISTENT);
  	REGISTER_LONG_CONSTANT("SNMP_COUNTER64", ASN_COUNTER64, CONST_CS | CONST_PERSISTENT);
  
 +	REGISTER_LONG_CONSTANT("SNMP_VERSION_1", SNMP_VERSION_1, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_VERSION_2c", SNMP_VERSION_2c, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_VERSION_3", SNMP_VERSION_3, CONST_CS | CONST_PERSISTENT);
  	return SUCCESS;
  }
  /* }}} */
 @@ -441,20 +598,30 @@
  static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_DC)
  {
  
 -	REGISTER_LONG_CONSTANT("SNMP_VALUE_LIBRARY", SNMP_VALUE_LIBRARY, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_VALUE_PLAIN", SNMP_VALUE_PLAIN, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_VALUE_OBJECT", SNMP_VALUE_OBJECT, CONST_CS | CONST_PERSISTENT);
 +static void php_snmp_object_free_storage(void *object TSRMLS_DC)
 +{
 +	php_snmp_object *intern = (php_snmp_object *)object;
 +	
 +	if (!intern) {
 +		return;
 +	}
  
 -	REGISTER_LONG_CONSTANT("SNMP_BIT_STR", ASN_BIT_STR, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_OCTET_STR", ASN_OCTET_STR, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_OPAQUE", ASN_OPAQUE, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_NULL", ASN_NULL, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_OBJECT_ID", ASN_OBJECT_ID, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_IPADDRESS", ASN_IPADDRESS, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_COUNTER", ASN_GAUGE, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_UNSIGNED", ASN_UNSIGNED, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_TIMETICKS", ASN_TIMETICKS, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_UINTEGER", ASN_UINTEGER, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_INTEGER", ASN_INTEGER, CONST_CS | CONST_PERSISTENT);
 -	REGISTER_LONG_CONSTANT("SNMP_COUNTER64", ASN_COUNTER64, CONST_CS | CONST_PERSISTENT);
 +	netsnmp_session_free(&(intern->session));
  
 -	return SUCCESS;
 +	zend_object_std_dtor(&intern->zo TSRMLS_CC);
  }
 -/* }}} */
  
 -/* {{{ PHP_MSHUTDOWN_FUNCTION
 - */
 -PHP_MSHUTDOWN_FUNCTION(snmp)
 +static zend_object_value php_snmp_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
  {
 -	snmp_shutdown("snmpapp");
 +	zval *tmp;
 +	zend_object_value retval;
 +	php_snmp_object *intern;
  
 -	return SUCCESS;
 -}
 -/* }}} */
 +	/* Allocate memory for it */
 +	intern = emalloc(sizeof(php_snmp_object));
 +	memset(&intern->zo, 0, sizeof(php_snmp_object));
  
 -/* {{{ PHP_MINFO_FUNCTION
 - */
 -PHP_MINFO_FUNCTION(snmp)
 -{
 -	php_info_print_table_start();
 -#ifdef HAVE_NET_SNMP
 -	php_info_print_table_row(2, "NET-SNMP Support", "enabled");
 -	php_info_print_table_row(2, "NET-SNMP Version", netsnmp_get_version());
 -#else
 -	php_info_print_table_row(2, "UCD-SNMP Support", "enabled");
 -	php_info_print_table_row(2, "UCD-SNMP Version", VersionInfo);
 -#endif
 -	php_info_print_table_end();
 +	zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
 +	zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *));
 +
 +	retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_snmp_object_free_storage, NULL TSRMLS_CC);
 +	retval.handlers = (zend_object_handlers *) &php_snmp_object_handlers;
 +
 +	return retval;
 +	
  }
 -/* }}} */
  
 -static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_DC)
 +static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_DC, int valueretrieval)
  {
   	zval *val;
  -#if I64CHARSZ > 2047
  -	char buf[I64CHARSZ + 1];
  -#else


  +	char *dbuf = (char *)NULL;
  +	int buflen = sizeof(sbuf) - 1;
  +	int val_len = vars->val_len;
  +	
 +	if (SNMP_G(valueretrieval) == SNMP_VALUE_LIBRARY) {
 +	if (valueretrieval == SNMP_VALUE_LIBRARY) {
  +		val_len += 32; /* snprint_value will add type info into value, make some space for it */
  +	}
 +
  
 -	buf[0] = 0;
  +	/* use emalloc() for large values, use static array otherwize */
  +	if(val_len > buflen){
  +		if ((dbuf = (char *)emalloc(val_len + 1))) {
  +			buf = dbuf;
  +			buflen = val_len;
  +		} else {
  +			php_error_docref(NULL TSRMLS_CC, E_WARNING, "malloc() failed: %s, fallback to static array", strerror(errno));
  +		}
 +	}
  
 -	buf[0] = 0;
 +	*buf = 0;
  
  	if (SNMP_G(valueretrieval) == SNMP_VALUE_LIBRARY) {
 -#ifdef HAVE_NET_SNMP
 +	}
  
 -	if (SNMP_G(valueretrieval) == SNMP_VALUE_LIBRARY) {
 -#ifdef HAVE_NET_SNMP
  -		snprint_value(buf, sizeof(buf), vars->name, vars->name_length, vars);
  -#else
  -		sprint_value(buf,vars->name, vars->name_length, vars);
 -#endif
 -#endif
 +	*buf = 0;
 +
 +	if (valueretrieval == SNMP_VALUE_LIBRARY) {
  +		SNMP_SNPRINT_VALUE(buf, buflen, vars->name, vars->name_length, vars);
   		ZVAL_STRING(snmpval, buf, 1);
   		return;
   	}
 @@ -476,20 +643,15 @@
 @@ -476,20 +571,15 @@
   		break;
   
   	case ASN_OBJECT_ID:		/* 0x06, asn1.h */
  -#ifdef HAVE_NET_SNMP


  -		sprint_objid(buf, vars->val.objid, vars->val_len / sizeof(oid));
  -#endif
  -
  +		SNMP_SNPRINT_OBJID(buf, buflen, vars->val.objid, vars->val_len / sizeof(oid));
  		ZVAL_STRING(val, buf, 1);
  		break;
  
  		ZVAL_STRING(val, buf, 1);
  		break;
  
   	case ASN_IPADDRESS:		/* 0x40, snmp_impl.h */
  -		snprintf(buf, sizeof(buf)-1, "%d.%d.%d.%d",
  -		         (vars->val.string)[0], (vars->val.string)[1],
  -		         (vars->val.string)[2], (vars->val.string)[3]);
 -		buf[sizeof(buf)-1]=0;
 -		buf[sizeof(buf)-1]=0;
  +		snprintf(buf, buflen, "%d.%d.%d.%d",
  +			 (vars->val.string)[0], (vars->val.string)[1],
  +			 (vars->val.string)[2], (vars->val.string)[3]);
 +		buf[buflen]=0;
  		ZVAL_STRING(val, buf, 1);
  		break;
 +		buf[buflen]=0;
  		ZVAL_STRING(val, buf, 1);
  		break;
   
 @@ -498,17 +660,35 @@
 @@ -498,17 +588,35 @@
   	/* ASN_UNSIGNED is the same as ASN_GAUGE */
   	case ASN_TIMETICKS:		/* 0x43, snmp_impl.h */
   	case ASN_UINTEGER:		/* 0x47, snmp_impl.h */
  -		snprintf(buf, sizeof(buf)-1, "%lu", *vars->val.integer);
  -		buf[sizeof(buf)-1]=0;
  +		snprintf(buf, buflen, "%lu", *vars->val.integer);
 +		buf[buflen]=0;
  		ZVAL_STRING(val, buf, 1);
  		break;
  
 +		buf[buflen]=0;
  		ZVAL_STRING(val, buf, 1);
  		break;
  
   	case ASN_INTEGER:		/* 0x02, asn1.h */
  -		snprintf(buf, sizeof(buf)-1, "%ld", *vars->val.integer);
  -		buf[sizeof(buf)-1]=0;
  +		snprintf(buf, buflen, "%ld", *vars->val.integer);
  +		buf[buflen]=0;
 +		ZVAL_STRING(val, buf, 1);
 +		ZVAL_STRING(val, buf, 1);
  +		break;
  +
  +#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
  +	case ASN_OPAQUE_FLOAT:		/* 0x78, asn1.h */
  +		snprintf(buf, buflen, "%f", *vars->val.floatVal);
 +		ZVAL_STRING(val, buf, 1);
 +		ZVAL_STRING(val, buf, 1);
  +		break;
  +
  +	case ASN_OPAQUE_DOUBLE:		/* 0x79, asn1.h */
  +		snprintf(buf, buflen, "%Lf", *vars->val.doubleVal);


  +		break;
  +
  +	case ASN_OPAQUE_I64:		/* 0x80, asn1.h */
  +		printI64(buf, vars->val.counter64);
  		ZVAL_STRING(val, buf, 1);
  		break;
  
  		ZVAL_STRING(val, buf, 1);
  		break;
  
  +	case ASN_OPAQUE_U64:		/* 0x81, asn1.h */
  +#endif
   	case ASN_COUNTER64:		/* 0x46, snmp_impl.h */
   		printU64(buf, vars->val.counter64);
   		ZVAL_STRING(val, buf, 1);
 @@ -516,6 +696,7 @@
 @@ -516,10 +624,11 @@
   
   	default:
   		ZVAL_STRING(val, "Unknown value type", 1);
  +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown value type: %u", vars->type);
   		break;
   	}
   
 @@ -527,26 +708,20 @@
 -	if (SNMP_G(valueretrieval) == SNMP_VALUE_PLAIN) {
 +	if (valueretrieval == SNMP_VALUE_PLAIN) {
  		*snmpval = *val;
  		zval_copy_ctor(snmpval);
  	} else {
 @@ -527,26 +636,21 @@
   		add_property_long(snmpval, "type", vars->type);
   		add_property_zval(snmpval, "value", val);
   	}
  +	if(dbuf){ /* malloc was used to store value */


  -							char *objid,
  -							char type,
  -							char* value) 
  +							struct objid_set *objid_set,
 +							int non_repeaters, int max_repetitions)
 +							int non_repeaters, int max_repetitions,
 +							int valueretrieval)
   {
   	struct snmp_session *ss;
   	struct snmp_pdu *pdu=NULL, *response;
 @@ -562,14 +737,23 @@
 @@ -562,14 +666,23 @@
   	int keepwalking=1;
   	char *err;
   	zval *snmpval = NULL;
 +	int snmp_errno;
  
 -	if (st >= SNMP_CMD_WALK) { /* walk */
 +	int snmp_errno;
 +
  +	/* we start with retval=FALSE. If any actual data is aquired, retval will be set to appropriate type */
  +	RETVAL_FALSE;
 +
  
 -	if (st >= SNMP_CMD_WALK) { /* walk */
  +	if (st & SNMP_CMD_WALK) {
  +		if (objid_set->count > 1) {
  +			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Multi OID walks are not supported!");
  +			RETURN_FALSE;


   			} else {
  -				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid);
  +				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid_set->vars[0].oid);
  +				RETURN_FALSE;
  			}
  			}
   		}
   
 @@ -578,6 +762,9 @@
 @@ -578,6 +691,9 @@
   			rootlen = sizeof(objid_mib) / sizeof(oid);
   			gotroot = 1;
   		}
  +


  +		name_length = rootlen;
   	}
   
   	if ((ss = snmp_open(session)) == NULL) {
 @@ -587,51 +774,49 @@
 @@ -587,51 +703,49 @@
   		RETURN_FALSE;
   	}
   
  -	if (st >= SNMP_CMD_WALK) {


  -				snmp_close(ss);
  -				RETURN_FALSE;
  +		if (st & (SNMP_CMD_GET | SNMP_CMD_GETNEXT)) {
  +			pdu = snmp_pdu_create((st & SNMP_CMD_GET) ? SNMP_MSG_GET : SNMP_MSG_GETNEXT);
 +			for (count = 0; count < objid_set->count; count++){
 +				name_length = MAX_OID_LEN;
 +			for (count = 0; count < objid_set->count; count++){
 +				name_length = MAX_OID_LEN;
  +				if (!snmp_parse_oid(objid_set->vars[count].oid, name, &name_length)) {
  +					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid_set->vars[count].oid);
  +				} else {
  +					snmp_add_null_var(pdu, name, name_length);


  +						snmp_free_pdu(pdu);
  +						snmp_close(ss);
  +						RETURN_FALSE;
  +					}
 +				}
 +				}
  +			}
  +		} else if (st & SNMP_CMD_WALK) {
   			if (session->version == SNMP_VERSION_1) {
   				pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);


  +				pdu->max_repetitions = max_repetitions;
   			}
   			snmp_add_null_var(pdu, name, name_length);
   		}
 @@ -640,95 +825,90 @@
 @@ -640,95 +754,91 @@
   		status = snmp_synch_response(ss, pdu, &response);
   		if (status == STAT_SUCCESS) {
   			if (response->errstat == SNMP_ERR_NOERROR) {
  +				if (st & SNMP_CMD_SET) {


   					}
   
  -					if (st == SNMP_CMD_GET) {
  +					MAKE_STD_ZVAL(snmpval);
 +					php_snmp_getvalue(vars, snmpval TSRMLS_CC);
 +					php_snmp_getvalue(vars, snmpval TSRMLS_CC, valueretrieval);
  +
 +					if(objid_set->array_output && Z_TYPE_P(return_value) == IS_BOOL) {
 +						array_init(return_value);
 +					}
 +					
 +					if (st & SNMP_ASSOC_OUTPUT) {
 +						SNMP_SNPRINT_OBJID(buf2, sizeof(buf2), vars->name, vars->name_length);
 +						add_assoc_zval(return_value, buf2, snmpval);
 +					} else if (objid_set->array_output) {
 +						add_next_index_zval(return_value, snmpval);
 +					if (objid_set->array_output) {
 +						if (Z_TYPE_P(return_value) == IS_BOOL) {
 +							array_init(return_value);
 +						}
 +						if (st & SNMP_NUMERIC_KEYS) {
 +							add_next_index_zval(return_value, snmpval);
 +						} else {
 +							SNMP_SNPRINT_OBJID(buf2, sizeof(buf2), vars->name, vars->name_length);
 +							add_assoc_zval(return_value, buf2, snmpval);
 +						}
  +					} else {
   						*return_value = *snmpval;
   						zval_copy_ctor(return_value);
   						zval_ptr_dtor(&snmpval);


  +					if (objid_set->array_output) {
   						zval_dtor(return_value);
   					}
   					RETURN_FALSE;
 @@ -736,14 +916,16 @@
 @@ -736,14 +846,16 @@
   			}
   		} else if (status == STAT_TIMEOUT) {
   			php_error_docref(NULL TSRMLS_CC, E_WARNING, "No response from %s", session->peername);
  -			if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {


  +			if (objid_set->array_output) {
   				zval_dtor(return_value);
   			}
   			snmp_close(ss);
 @@ -757,115 +939,569 @@
 @@ -757,212 +869,174 @@
   }
   /* }}} */
   
  -/* {{{ php_snmp
Line 852 (now 952), was 10 lines, now 9 lines

  -* st=5-8 ** Reserved **
  -* st=SNMP_CMD_SET  set() - query an agent and set a single value
  +/* {{{ php_snmp_parse_oid
   *
 +* Unified parser for OID (and type, value for SNMP_SET command)
 +* Used in all SNMP protocol version functions
 +* Parser for OID (and type, value for SNMP_SET command)
   */
  -static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) 
  +
  +static int php_snmp_parse_oid(int st, struct objid_set *objid_set, zval **oid, zval **type, zval **value)


   
  -	if (st == SNMP_CMD_SET) {
  -		if (zend_parse_parameters(argc TSRMLS_CC, "sssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len, &stype, &stype_len, &value, &value_len, &timeout, &retries) == FAILURE) {
  -			return;
 +	if (Z_TYPE_PP(oid) != IS_ARRAY) {
 +		if (Z_ISREF_PP(oid)) {
 +			SEPARATE_ZVAL(oid);
  		}
 -		}
  -	} else {
  -		/* SNMP_CMD_GET
  -		 * SNMP_CMD_GETNEXT
  -		 * SNMP_CMD_WALK
  -		 * SNMP_CMD_REALWALK
  -		 */
  -		if (zend_parse_parameters(argc TSRMLS_CC, "sss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len, &timeout, &retries) == FAILURE) {
  -			return;
 +	if (Z_TYPE_PP(oid) != IS_ARRAY) {
 +		if (Z_ISREF_PP(oid)) {
 +			SEPARATE_ZVAL(oid);
  		}
  +		convert_to_string_ex(oid);
  +	} else if (Z_TYPE_PP(oid) == IS_ARRAY) {
  +		zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(oid), &pos_oid);
 +	}
 +
  	}
 -	
 -	if (st == SNMP_CMD_SET) {
 -		type = stype[0];
 -	} 
 -
 -	snmp_sess_init(&session);
 -	strlcpy(hostname, a1, sizeof(hostname));
 -	if ((pptr = strchr (hostname, ':'))) {
 -		remote_port = strtol (pptr + 1, NULL, 0);
 -	}
 -
 -	session.peername = hostname;
 -	session.remote_port = remote_port;
 -	session.version = version;
 -	/*
 -	* FIXME: potential memory leak
 -	* This is a workaround for an "artifact" (Mike Slifcak)
 -	* in (at least) ucd-snmp 3.6.1 which frees
 -	* memory it did not allocate
 -	*/
 -#ifdef UCD_SNMP_HACK
 -	session.community = (u_char *)strdup(a2); /* memory freed by SNMP library, strdup NOT estrdup */
 -#else
 -	session.community = (u_char *)a2;
 -#endif
 -	session.community_len = a2_len;
 -	session.retries = retries;
 -	session.timeout = timeout;
 -	
 -	session.authenticator = NULL;
 -
 -	php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session, a3, type, value);
 -}
 -/* }}} */
 -
 -/* {{{ proto string snmpget(string host, string community, string object_id [, int timeout [, int retries]]) 
 -   Fetch a SNMP object */
 -PHP_FUNCTION(snmpget)
 -{
 -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_1);
 -}
 -/* }}} */
 -
 -/* {{{ proto string snmpgetnext(string host, string community, string object_id [, int timeout [, int retries]]) 
 -   Fetch a SNMP object */
 -PHP_FUNCTION(snmpgetnext)
 -{
 -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_1);
 -}
 -/* }}} */
 -
 -/* {{{ proto array snmpwalk(string host, string community, string object_id [, int timeout [, int retries]]) 
 -   Return all objects under the specified object id */
 -PHP_FUNCTION(snmpwalk)
 -{
 -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_1);
 -}
 -/* }}} */
  
 -/* {{{ proto array snmprealwalk(string host, string community, string object_id [, int timeout [, int retries]])
 -   Return all objects including their respective object id withing the specified one */
 -PHP_FUNCTION(snmprealwalk)
 -{
 -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_1);
 -}
 -/* }}} */
  +	if (st & SNMP_CMD_SET) {
  +		if (Z_TYPE_PP(type) != IS_ARRAY) {
  +			if (Z_ISREF_PP(type)) {
  +				SEPARATE_ZVAL(type);
  +			}
  +			convert_to_string_ex(type);
  +		} else if (Z_TYPE_PP(type) == IS_ARRAY) {
  +			zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(type), &pos_type);
 +		}
 +
 +		}
  
 -/* {{{ proto bool snmp_get_quick_print(void)
 -   Return the current status of quick_print */
 -PHP_FUNCTION(snmp_get_quick_print)
 -{
 -	if (zend_parse_parameters_none() == FAILURE) {
 -		return;
  +		if (Z_TYPE_PP(value) != IS_ARRAY) {
  +			if (Z_ISREF_PP(value)) {
  +				SEPARATE_ZVAL(value);
  +			}
  +			convert_to_string_ex(value);
  +		} else if (Z_TYPE_PP(value) == IS_ARRAY) {
  +			zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(value), &pos_value);
  +		}
 +	}
 +
  	}
  
 -#ifdef HAVE_NET_SNMP
 -	RETURN_BOOL(netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT));
 -#else
 -	RETURN_BOOL(snmp_get_quick_print());
 -#endif
 -}
 -/* }}} */
  +	objid_set->count = 0;
 +	objid_set->array_output = ((st & (SNMP_CMD_WALK | SNMP_ASSOC_OUTPUT)) ? TRUE : FALSE);
 +	objid_set->array_output = ((st & SNMP_CMD_WALK) ? TRUE : FALSE);
  +	if (Z_TYPE_PP(oid) == IS_STRING) {
  +		objid_set->vars[objid_set->count].oid = Z_STRVAL_PP(oid);
  +		if (st & SNMP_CMD_SET) {
  +			if (Z_TYPE_PP(type) == IS_STRING && Z_TYPE_PP(value) == IS_STRING) {


  +						php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s': no type set", Z_STRVAL_PP(tmp_oid));
  +						return FALSE;
  +					}
  +				}
 +
  
 -/* {{{ proto void snmp_set_quick_print(int quick_print)
 -   Return all objects including their respective object id withing the specified one */
 -PHP_FUNCTION(snmp_set_quick_print)
 -{
 -	long a1;
  +				if (Z_TYPE_PP(value) == IS_STRING) {
  +					objid_set->vars[objid_set->count].value = Z_STRVAL_PP(value);
  +				} else if (Z_TYPE_PP(value) == IS_ARRAY) {
  +					if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(value), (void **) &tmp_value, &pos_value)) {
Line 978 (now 1161), was 64 lines, now 43 lines

  +						return FALSE;
  +					}
  +				}
  +			}
 +
  
 -	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 -		return;
  +			if (objid_set->count++ >= SNMP_MAXOIDS_IN_PDU) {
  +				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not process more than %u OIDs in singe GET/GETNEXT/SET query", SNMP_MAXOIDS_IN_PDU);
  +				return FALSE;
  +			}
  		}
 +		}
   	}
 -	
 -	if (st == SNMP_CMD_SET) {
 -		type = stype[0];
 -	} 
 -
 -	snmp_sess_init(&session);
 -	strlcpy(hostname, a1, sizeof(hostname));
 -	if ((pptr = strchr (hostname, ':'))) {
 -		remote_port = strtol (pptr + 1, NULL, 0);
 -	}
 -
 -	session.peername = hostname;
 -	session.remote_port = remote_port;
 -	session.version = version;
 -	/*
 -	* FIXME: potential memory leak
 -	* This is a workaround for an "artifact" (Mike Slifcak)
 -	* in (at least) ucd-snmp 3.6.1 which frees
 -	* memory it did not allocate
 -	*/
 -#ifdef UCD_SNMP_HACK
 -	session.community = (u_char *)strdup(a2); /* memory freed by SNMP library, strdup NOT estrdup */
  
 -#ifdef HAVE_NET_SNMP
 -	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, (int) a1);
  -#else
 -	session.community = (u_char *)a2;
 -	snmp_set_quick_print((int)a1);
  -#endif
 -	session.community_len = a2_len;
 -	session.retries = retries;
 -	session.timeout = timeout;
 -	
 -	session.authenticator = NULL;
  
 -	php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session, a3, type, value);
  +	return (objid_set->count > 0);
  }
  /* }}} */
  }
  /* }}} */
   
 -/* {{{ proto string snmpget(string host, string community, string object_id [, int timeout [, int retries]]) 
 -   Fetch a SNMP object */
 -PHP_FUNCTION(snmpget)
 -#ifdef HAVE_NET_SNMP
 -/* {{{ proto void snmp_set_enum_print(int enum_print)
 -   Return all values that are enums with their enum value instead of the raw integer */
 -PHP_FUNCTION(snmp_set_enum_print)
  +/* {{{ netsnmp_session_init
 +	allocates memory for session and session->peername, caller should efree() it manually if using function in session-less maner
 +	allocates memory for session and session->peername, caller should free it manually using netsnmp_session_free()
  +*/
  +static int netsnmp_session_init(php_snmp_session **session_p, int version, char *hostname, char *community, int timeout, int retries)
   {
 -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_1);
 -	long a1;
  +	int remote_port = SNMP_PORT;
  +	php_snmp_session *session;
  +	char *pptr;
 +
  
 -	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 -		return;
  +	*session_p = (php_snmp_session *)emalloc(sizeof(php_snmp_session));
  +	session = *session_p;
  +	if (session == NULL) {
  +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed allocating session");
Line 1048 (now 1210), was 510 lines, now 58 lines

  +
  +	session->peername = emalloc(MAX_NAME_LEN);
  +	if(session->peername == NULL) {
  +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while copying hostname");
 +		netsnmp_session_free(session);
 +		return (-1);
 +	}
 +
 +		netsnmp_session_free(&session);
 +		return (-1);
  	}
  
 -	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, (int) a1);
 -} 
 -/* }}} */
 -
 -/* {{{ proto void snmp_set_oid_output_format(int oid_format)
 -   Set the OID output format. */
 -PHP_FUNCTION(snmp_set_oid_output_format)
 -{
 -	long a1;
 -
 -	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 -		return;
  +	/* Reading the hostname and its optional non-default port number */
  +	strlcpy(session->peername, hostname, MAX_NAME_LEN);
  +	if ((pptr = strchr(session->peername, ':'))) {
  +		remote_port = strtol(pptr + 1, NULL, 0);
 +	}
 +
  	}
  
 -	switch ((int) a1) {
 -		case 0:
 -		case NETSNMP_OID_OUTPUT_FULL:
 -			a1 = NETSNMP_OID_OUTPUT_FULL;
 -			break;
 -
 -		default:
 -		case NETSNMP_OID_OUTPUT_NUMERIC:
 -			a1 = NETSNMP_OID_OUTPUT_NUMERIC;
 -			break;
 -	}
  +	session->remote_port = remote_port;
 +
  
 -	netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, a1);
 -} 
 -/* }}} */
  +	if (version == SNMP_VERSION_3) {
  +		/* Setting the security name. */
  +		session->securityName = strdup(community);
  +		session->securityNameLen = strlen(session->securityName);
  +	} else {
  +		session->authenticator = NULL;
 +
  +#ifdef UCD_SNMP_HACK
  +		session->community = (u_char *)strdup(community); /* memory freed by SNMP library, strdup NOT estrdup */
  +#else
  +		session->community = (u_char *)community;
 +#endif
 +		session->community_len = strlen(community);
 +	}
 +
 +	session->retries = retries;
 +	session->timeout = timeout;
 +	return (0);
  }
  /* }}} */
  
 -/* {{{ proto string snmpgetnext(string host, string community, string object_id [, int timeout [, int retries]]) 
 -   Fetch a SNMP object */
 -PHP_FUNCTION(snmpgetnext)
 +/* {{{ int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
 +   Set the security level in the snmpv3 session */
 +static int netsnmp_session_set_sec_level(struct snmp_session *s, char *level TSRMLS_DC)
  {
 -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_1);
 +	if (!strcasecmp(level, "noAuthNoPriv") || !strcasecmp(level, "nanp")) {
 +		s->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
 +	} else if (!strcasecmp(level, "authNoPriv") || !strcasecmp(level, "anp")) {
 +		s->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
 +	} else if (!strcasecmp(level, "authPriv") || !strcasecmp(level, "ap")) {
 +		s->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
 +	} else {
 +		return (-1);
 +	}
 +	return (0);
  }
  /* }}} */
  
 -/* {{{ proto array snmpwalk(string host, string community, string object_id [, int timeout [, int retries]]) 
 -   Return all objects under the specified object id */
 -PHP_FUNCTION(snmpwalk)
 +/* {{{ int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot)
 +   Set the authentication protocol in the snmpv3 session */
 +static int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
  {
 -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_1);
 +	if (!strcasecmp(prot, "MD5")) {
 +		s->securityAuthProto = usmHMACMD5AuthProtocol;
 +		s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
 +	} else if (!strcasecmp(prot, "SHA")) {
 +		s->securityAuthProto = usmHMACSHA1AuthProtocol;
 +		s->securityAuthProtoLen = OIDSIZE(usmHMACSHA1AuthProtocol);
 +	} else {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown authentication protocol '%s'", prot TSRMLS_DC);
 +		return (-1);
 +	}
 +	return (0);
  }
  /* }}} */
  
 -/* {{{ proto array snmprealwalk(string host, string community, string object_id [, int timeout [, int retries]])
 -   Return all objects including their respective object id withing the specified one */
 +/* {{{ int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot)
 +   Set the security protocol in the snmpv3 session */
 +static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
 +{
 +	if (!strcasecmp(prot, "DES")) {
 +		s->securityPrivProto = usmDESPrivProtocol;
 +		s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
 +#ifdef HAVE_AES
 +	} else if (!strcasecmp(prot, "AES128")
 +#ifdef SNMP_VALIDATE_ERR
 +/* 
 +* In Net-SNMP before 5.2, the following symbols exist:
 +* usmAES128PrivProtocol, usmAES192PrivProtocol, usmAES256PrivProtocol
 +* In an effort to be more standards-compliant, 5.2 removed the last two.
 +* As of 5.2, the symbols are:
 +* usmAESPrivProtocol, usmAES128PrivProtocol
 +* 
 +* As we want this extension to compile on both versions, we use the latter
 +* symbol on purpose, as it's defined to be the same as the former.
 +*
 +* However, in 5.2 the type of usmAES128PrivProtocol is a pointer, not an
 +* array, so we cannot use the OIDSIZE macro because it uses sizeof().
 +*
 +*/
 +		|| !strcasecmp(prot, "AES")) {
 +		s->securityPrivProto = usmAES128PrivProtocol;
 +		s->securityPrivProtoLen = USM_PRIV_PROTO_AES128_LEN;
 +#else			
 +	) {
 +		s->securityPrivProto = usmAES128PrivProtocol;
 +		s->securityPrivProtoLen = OIDSIZE(usmAES128PrivProtocol);
 +	} else if (!strcasecmp(prot, "AES192")) {
 +		s->securityPrivProto = usmAES192PrivProtocol;
 +		s->securityPrivProtoLen = OIDSIZE(usmAES192PrivProtocol);
 +	} else if (!strcasecmp(prot, "AES256")) {
 +		s->securityPrivProto = usmAES256PrivProtocol;
 +		s->securityPrivProtoLen = OIDSIZE(usmAES256PrivProtocol);
 +#endif
 +#endif
 +	} else {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown security protocol '%s'", prot);
 +		return (-1);
 +	}
 +	return (0);
 +}
 +/* }}} */
 +
 +/* {{{ int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass)
 +   Make key from pass phrase in the snmpv3 session */
 +static int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass TSRMLS_DC)
 +{
 +	int snmp_errno;
 +	s->securityAuthKeyLen = USM_AUTH_KU_LEN;
 +	if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
 +			(u_char *) pass, strlen(pass),
 +			s->securityAuthKey, &(s->securityAuthKeyLen)))) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for authentication pass phrase '%s': %s", pass, snmp_api_errstring(snmp_errno));
 +		return (-1);
 +	}
 +	return (0);
 +}
 +/* }}} */
 +
 +/* {{{ int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass)
 +   Make key from pass phrase in the snmpv3 session */
 +static int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass TSRMLS_DC)
 +{
 +	int snmp_errno;
 +
 +	s->securityPrivKeyLen = USM_PRIV_KU_LEN;
 +	if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
 +			pass, strlen(pass),
 +			s->securityPrivKey, &(s->securityPrivKeyLen)))) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for privacy pass phrase '%s': %s", pass, snmp_api_errstring(snmp_errno));
 +		return (-2);
 +	}
 +	return (0);
 +}
 +/* }}} */
 +
 +/* {{{ in netsnmp_session_set_contextEngineID(struct snmp_session *s, u_char * contextEngineID) */
 +static int netsnmp_session_set_contextEngineID(struct snmp_session *s, u_char * contextEngineID)
 +{
 +	size_t	ebuf_len = 32, eout_len = 0;
 +	u_char	*ebuf = (u_char *) malloc(ebuf_len); /* memory freed by SNMP library, strdup NOT estrdup */
 +
 +	if (ebuf == NULL) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "malloc failure setting contextEngineID");
 +		return (-1);
 +	}
 +	if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, contextEngineID)) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad engine ID value '%s'", contextEngineID);
 +		free(ebuf);
 +		return (-1);
 +	}
 +	s->contextEngineID = ebuf;
 +	s->contextEngineIDLen = eout_len;
 +	return (0);
 +}
 +/* }}} */
 +
 +/* {{{ php_set_security */
 +
 +static int netsnmp_session_set_security(struct snmp_session *session, char *sec_level, char *auth_protocol, char *auth_passphrase, char *priv_protocol, char *priv_passphrase, char *contextName, char *contextEngineID)
 +{
 +
 +	/* Setting the security level. */
 +	if (netsnmp_session_set_sec_level(session, sec_level)) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security level '%s'", sec_level);
 +		return (-1);
 +	}
 +
 +	if (session->securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
 +
 +		/* Setting the authentication protocol. */
 +		if (netsnmp_session_set_auth_protocol(session, auth_protocol)) {
 +			/* Warning message sent already, just bail out */
 +			return (-1);
 +		}
 +
 +		/* Setting the authentication passphrase. */
 +		if (netsnmp_session_gen_auth_key(session, auth_passphrase)) {
 +			/* Warning message sent already, just bail out */
 +			return (-1);
 +		}
 +
 +		if (session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
 +			/* Setting the security protocol. */
 +			if (netsnmp_session_set_sec_protocol(session, priv_protocol)) {
 +				/* Warning message sent already, just bail out */
 +				return (-1);
 +			}
 +
 +			/* Setting the security protocol passphrase. */
 +			if (netsnmp_session_gen_sec_key(session, priv_passphrase)) {
 +				/* Warning message sent already, just bail out */
 +				return (-1);
 +			}
 +		}
 +	}
 +
 +	/* Setting contextName if specified */
 +	if (contextName) {
 +		session->contextName = contextName;
 +		session->contextNameLen = strlen(contextName);
 +	}
 +
 +	/* Setting contextEngineIS if specified */
 +	if (contextEngineID && strlen(contextEngineID) && netsnmp_session_set_contextEngineID(session, contextEngineID)) {
 +		/* Warning message sent already, just bail out */
 +		return (-1);
 +	}
 +
 +	return (0);
 +}
 +/* }}} */
 +
 +/* {{{ php_snmp
 +*
 +* Generic community based SNMP handler for all versions.
 +* This function makes use of the internal SNMP object fetcher.
 +*
 +*/
 +static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 +{
 +	zval **oid, **value, **type, *z_session;
 +	char *a1, *a2, *a3, *a4, *a5, *a6, *a7;
 +	int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len;
 +	struct snmp_session *session;
 +	long timeout = SNMP_DEFAULT_TIMEOUT;
 +	long retries = SNMP_DEFAULT_RETRIES;
 +	int non_repeaters = 0;
 +	int max_repetitions = 20;
 +	int argc = ZEND_NUM_ARGS();
 +	struct objid_set objid_set;
 +	int session_less_mode = TRUE;
 +	
 +	if (argc <= 4 && zend_parse_parameters(1, "z", &z_session) == SUCCESS && Z_TYPE_P(z_session) == IS_RESOURCE) {
 +		ZEND_FETCH_RESOURCE(session, php_snmp_session *, &z_session, -1, PHP_SNMP_SESSION_RES_NAME, le_snmp_session);
 +		if (session) {
 +			session_less_mode = FALSE;
 +		}
 +	}
 +
 +	if (session_less_mode) {
 +		if (version == SNMP_VERSION_3) {
 +			if (st & SNMP_CMD_SET) {
 +				if (zend_parse_parameters(argc TSRMLS_CC, "sssssssZZZ|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 +					&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &oid, &type, &value, &timeout, &retries) == FAILURE) {
 +					RETURN_FALSE;
 +				}
 +			} else {
 +				/* SNMP_CMD_GET
 +				 * SNMP_CMD_GETNEXT
 +				 * SNMP_CMD_WALK
 +				 */
 +				if (zend_parse_parameters(argc TSRMLS_CC, "sssssssZ|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 +					&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &oid, &timeout, &retries) == FAILURE) {
 +					RETURN_FALSE;
 +				}
 +			}
 +		} else {
 +			if (st & SNMP_CMD_SET) {
 +				if (zend_parse_parameters(argc TSRMLS_CC, "ssZZZ|ll", &a1, &a1_len, &a2, &a2_len, &oid, &type, &value, &timeout, &retries) == FAILURE) {
 +					RETURN_FALSE;
 +				}
 +			} else {
 +				/* SNMP_CMD_GET
 +				 * SNMP_CMD_GETNEXT
 +				 * SNMP_CMD_WALK
 +				 */
 +				if (zend_parse_parameters(argc TSRMLS_CC, "ssZ|ll", &a1, &a1_len, &a2, &a2_len, &oid, &timeout, &retries) == FAILURE) {
 +					RETURN_FALSE;
 +				}
 +			}
 +		}
 +	} else {
 +		if (st & SNMP_CMD_SET) {
 +			if (zend_parse_parameters(argc TSRMLS_CC, "rZZZ", &z_session, &oid, &type, &value) == FAILURE) {
 +				RETURN_FALSE;
 +			}
 +		} else if (st & SNMP_CMD_WALK) {
 +			if (zend_parse_parameters(argc TSRMLS_CC, "rZ|ll", &z_session, &oid, &non_repeaters, &max_repetitions) == FAILURE) {
 +				RETURN_FALSE;
 +			}
 +		} else {
 +			/* SNMP_CMD_GET
 +			 * SNMP_CMD_GETNEXT
 +			 */
 +			if (zend_parse_parameters(argc TSRMLS_CC, "rZ", &z_session, &oid) == FAILURE) {
 +				RETURN_FALSE;
 +			}
 +		}
 +	}
 +
 +	if (!php_snmp_parse_oid(st, &objid_set, oid, type, value)) {
 +		RETURN_FALSE;
 +	}
 +
 +	if (session_less_mode && netsnmp_session_init(&session, version, a1, a2, timeout, retries)) {
 +		RETURN_FALSE;
 +	}
 +
 +	if (version == SNMP_VERSION_3 && session_less_mode && netsnmp_session_set_security(session, a3 TSRMLS_CC, a4 TSRMLS_CC, a5 TSRMLS_CC, a6 TSRMLS_CC, a7 TSRMLS_CC, NULL, NULL)) {
 +		/* Warning message sent already, just bail out */
 +		RETURN_FALSE;
 +	}
 +
 +	php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, session, &objid_set, non_repeaters, max_repetitions);
 +	if (session_less_mode) {
 +		netsnmp_session_free(session);
 +	}
 +}
 +/* }}} */
 +
 +/* {{{ proto resource snmp_session_open(int version, string host, string community [, int timeout [, int retries]])
 +	Initialize SNMP session */
 +PHP_FUNCTION(snmp_session_open)
 +{
 +	php_snmp_session *session;
 +	char *a1, *a2;
 +	int a1_len, a2_len;
 +	long timeout = SNMP_DEFAULT_TIMEOUT;
 +	long retries = SNMP_DEFAULT_RETRIES;
 +	int version = SNMP_DEFAULT_VERSION;
 +	int argc = ZEND_NUM_ARGS();
 +
 +	if (zend_parse_parameters(argc TSRMLS_CC, "lss|ll", &version, &a1, &a1_len, &a2, &a2_len, &timeout, &retries) == FAILURE) {
 +		return;
 +	}
 +
 +	if (version != SNMP_VERSION_1 && version != SNMP_VERSION_2c && version != SNMP_VERSION_3) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP protocol version");
 +		return;
 +	}
 +
 +	if (netsnmp_session_init(&session, version, a1, a2, timeout, retries)) {
 +		return;
 +	}
 +	
 +	ZEND_REGISTER_RESOURCE(return_value, session, le_snmp_session);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmpget(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Fetch a SNMP object */
 +PHP_FUNCTION(snmpget)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_1);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmprealget(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Fetch a SNMP object */
 +PHP_FUNCTION(snmprealget)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_GET | SNMP_ASSOC_OUTPUT), SNMP_VERSION_1);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmpgetnext(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Fetch a SNMP object */
 +PHP_FUNCTION(snmpgetnext)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_1);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmprealgetnext(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Fetch a SNMP object */
 +PHP_FUNCTION(snmprealgetnext)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_GETNEXT | SNMP_ASSOC_OUTPUT), SNMP_VERSION_1);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmpwalk(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Return all objects under the specified object id */
 +PHP_FUNCTION(snmpwalk)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_1);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmprealwalk(string host, string community, mixed object_id [, int timeout [, int retries]])
 +   Return all objects including their respective object id withing the specified one */
  PHP_FUNCTION(snmprealwalk)
  {
 -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_1);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_ASSOC_OUTPUT), SNMP_VERSION_1);
 +}
 +/* }}} */
 +
 +/* {{{ proto bool snmpset(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) 
 +   Set the value of a SNMP object */
 +PHP_FUNCTION(snmpset)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_1);
 +}
 +/* }}} */
 +
 +/* {{{ proto bool snmp_session_close(resource $session) */
 +PHP_FUNCTION(snmp_session_close)
 +{
 +	zval *z_session;
 +	php_snmp_session *session;
 +	int argc = ZEND_NUM_ARGS();
 +
 +	if (zend_parse_parameters(argc TSRMLS_CC, "r", &z_session) == FAILURE) {
 +		RETURN_FALSE;
 +	}
 +
 +	ZEND_FETCH_RESOURCE(session, php_snmp_session *, &z_session, -1, PHP_SNMP_SESSION_RES_NAME, le_snmp_session);
 +
 +	RETURN_BOOL(zend_list_delete(Z_LVAL_P(z_session)) == SUCCESS);
 +
  }
  /* }}} */
  
 @@ -885,14 +1521,14 @@
  }
  /* }}} */
  
 -/* {{{ proto void snmp_set_quick_print(int quick_print)
 +/* {{{ proto bool snmp_set_quick_print(int quick_print)
     Return all objects including their respective object id withing the specified one */
  PHP_FUNCTION(snmp_set_quick_print)
  {
  	long a1;
  
  	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 -		return;
 +		RETURN_FALSE;
  	}
  
  #ifdef HAVE_NET_SNMP
 @@ -900,32 +1536,34 @@
  #else
  	snmp_set_quick_print((int)a1);
  #endif
 +	RETURN_TRUE;
  }
  /* }}} */
  
  #ifdef HAVE_NET_SNMP
 -/* {{{ proto void snmp_set_enum_print(int enum_print)
 +/* {{{ proto bool snmp_set_enum_print(int enum_print)
     Return all values that are enums with their enum value instead of the raw integer */
  PHP_FUNCTION(snmp_set_enum_print)
  {
  	long a1;
  
  	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 -		return;
 +		RETURN_FALSE;
  	}
  
  	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, (int) a1);
 +	RETURN_TRUE;
  } 
  /* }}} */
  
 -/* {{{ proto void snmp_set_oid_output_format(int oid_format)
 +/* {{{ proto bool snmp_set_oid_output_format(int oid_format)
     Set the OID output format. */
  PHP_FUNCTION(snmp_set_oid_output_format)
  {
  	long a1;
  
  	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 -		return;
 +		RETURN_FALSE;
  	}
  
  	switch ((int) a1) {
 @@ -941,380 +1579,162 @@
  	}
  
  	netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, a1);
 +	RETURN_TRUE;
  } 
  /* }}} */
   #endif
  
 -
  -/* {{{ proto int snmpset(string host, string community, string object_id, string type, mixed value [, int timeout [, int retries]]) 
  -   Set the value of a SNMP object */
  -PHP_FUNCTION(snmpset)
  -{


  -{
  -	if ((s) && (name)) {
  -		s->securityName = strdup(name);
  -		s->securityNameLen = strlen(s->securityName);
 -		return (0);
 -	}
 -	return (-1);
 -}
 -/* }}} */
 +/* {{{ proto bool snmp_session_set_security(resource session, string sec_level, [ string auth_protocol, string auth_passphrase [, string priv_protocol, string priv_passphrase [, string contextName [, string contextEngineID]]]])
 +	Set SNMPv3 security-related session parameters */
 +PHP_FUNCTION(snmp_session_set_security)
 +{
 +	zval *z_session;
 +	php_snmp_session *session;
 +	char *a1 = "", *a2 = "", *a3 = "", *a4 = "", *a5 = "", *a6 = "", *a7 = "";
 +	int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len;
 +	int argc = ZEND_NUM_ARGS();
 -		return (0);
 +		session->community_len = strlen(community);
  	}
 -	return (-1);
 +
 +	session->retries = retries;
 +	session->timeout = timeout;
 +	return (0);
  }
  /* }}} */
   
 -/* {{{ int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
 -   Set the security level in the snmpv3 session */
 -static int netsnmp_session_set_sec_level(struct snmp_session *s, char *level TSRMLS_DC)
 -{
 @@ -970,19 +1044,16 @@
     Set the security level in the snmpv3 session */
  static int netsnmp_session_set_sec_level(struct snmp_session *s, char *level TSRMLS_DC)
  {
  -	if ((s) && (level)) {
  -		if (!strcasecmp(level, "noAuthNoPriv") || !strcasecmp(level, "nanp")) {
  -			s->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
 -			return (0);
 -			return (0);
  -		} else if (!strcasecmp(level, "authNoPriv") || !strcasecmp(level, "anp")) {
  -			s->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
 -			return (0);
 -			return (0);
  -		} else if (!strcasecmp(level, "authPriv") || !strcasecmp(level, "ap")) {
  -			s->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
 -			return (0);
 -		}
 +	if (zend_parse_parameters(argc TSRMLS_CC, "r|sssssss", &z_session, &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 +		&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len) == FAILURE) {
 +		RETURN_FALSE;
  	}
 -	return (-1);
 -}
 -/* }}} */
  
 -/* {{{ int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot)
 -   Set the authentication protocol in the snmpv3 session */
 -static int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
 -{
 -			return (0);
 -		}
 +	if (!strcasecmp(level, "noAuthNoPriv") || !strcasecmp(level, "nanp")) {
 +		s->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
 +	} else if (!strcasecmp(level, "authNoPriv") || !strcasecmp(level, "anp")) {
 +		s->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
 +	} else if (!strcasecmp(level, "authPriv") || !strcasecmp(level, "ap")) {
 +		s->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
 +	} else {
 +		return (-1);
  	}
 -	return (-1);
 +	return (0);
  }
  /* }}} */
  
 @@ -990,18 +1061,17 @@
     Set the authentication protocol in the snmpv3 session */
  static int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
  {
  -	if ((s) && (prot)) {
  -		if (!strcasecmp(prot, "MD5")) {
  -			s->securityAuthProto = usmHMACMD5AuthProtocol;
  -			s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
  -			return (0);
  -		} else if (!strcasecmp(prot, "SHA")) {
  -			s->securityAuthProto = usmHMACSHA1AuthProtocol;
  -			s->securityAuthProtoLen = OIDSIZE(usmHMACSHA1AuthProtocol);
 -			return (0);
 -		}
 -	}
 -	return (-1);
 -}
 -/* }}} */
 +	ZEND_FETCH_RESOURCE(session, php_snmp_session *, &z_session, -1, PHP_SNMP_SESSION_RES_NAME, le_snmp_session);
  
 -/* {{{ int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot)
 -   Set the security protocol in the snmpv3 session */
 -static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
 -{
 -			return (0);
 -		}
 +	if (!strcasecmp(prot, "MD5")) {
 +		s->securityAuthProto = usmHMACMD5AuthProtocol;
 +		s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
 +	} else if (!strcasecmp(prot, "SHA")) {
 +		s->securityAuthProto = usmHMACSHA1AuthProtocol;
 +		s->securityAuthProtoLen = OIDSIZE(usmHMACSHA1AuthProtocol);
 +	} else {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown authentication protocol '%s'", prot TSRMLS_DC);
 +		return (-1);
  	}
 -	return (-1);
 +	return (0);
  }
  /* }}} */
  
 @@ -1009,13 +1079,11 @@
     Set the security protocol in the snmpv3 session */
  static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
  {
  -	if ((s) && (prot)) {
  -		if (!strcasecmp(prot, "DES")) {
  -			s->securityPrivProto = usmDESPrivProtocol;
  -			s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
 -			return (0);
 -#ifdef HAVE_AES
 -			return (0);
 +	if (!strcasecmp(prot, "DES")) {
 +		s->securityPrivProto = usmDESPrivProtocol;
 +		s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
  #ifdef HAVE_AES
  -		} else if (!strcasecmp(prot, "AES128")
 -#ifdef SNMP_VALIDATE_ERR
 -/* 
 -* In Net-SNMP before 5.2, the following symbols exist:
 -* usmAES128PrivProtocol, usmAES192PrivProtocol, usmAES256PrivProtocol
 -* In an effort to be more standards-compliant, 5.2 removed the last two.
 -* As of 5.2, the symbols are:
 -* usmAESPrivProtocol, usmAES128PrivProtocol
 -* 
 -* As we want this extension to compile on both versions, we use the latter
 -* symbol on purpose, as it's defined to be the same as the former.
 -*
 -* However, in 5.2 the type of usmAES128PrivProtocol is a pointer, not an
 -* array, so we cannot use the OIDSIZE macro because it uses sizeof().
 -*
 -*/
 +	} else if (!strcasecmp(prot, "AES128")
  #ifdef SNMP_VALIDATE_ERR
  /* 
  * In Net-SNMP before 5.2, the following symbols exist:
 @@ -1031,28 +1099,26 @@
  * array, so we cannot use the OIDSIZE macro because it uses sizeof().
  *
  */
  -			|| !strcasecmp(prot, "AES")) {
  -			s->securityPrivProto = usmAES128PrivProtocol;
  -			s->securityPrivProtoLen = USM_PRIV_PROTO_AES128_LEN;
  -			return (0);
 -#else			
 +		|| !strcasecmp(prot, "AES")) {
 +		s->securityPrivProto = usmAES128PrivProtocol;
 +		s->securityPrivProtoLen = USM_PRIV_PROTO_AES128_LEN;
  #else			
  -		) {
  -			s->securityPrivProto = usmAES128PrivProtocol;
  -			s->securityPrivProtoLen = OIDSIZE(usmAES128PrivProtocol);
  -			return (0);


  -		} else if (!strcasecmp(prot, "AES256")) {
  -			s->securityPrivProto = usmAES256PrivProtocol;
  -			s->securityPrivProtoLen = OIDSIZE(usmAES256PrivProtocol);
  -			return (0);
 -#endif
 -#endif
 +	) {
 +		s->securityPrivProto = usmAES128PrivProtocol;
 +		s->securityPrivProtoLen = OIDSIZE(usmAES128PrivProtocol);
 +	} else if (!strcasecmp(prot, "AES192")) {
 +		s->securityPrivProto = usmAES192PrivProtocol;
 +		s->securityPrivProtoLen = OIDSIZE(usmAES192PrivProtocol);
 +	} else if (!strcasecmp(prot, "AES256")) {
 +		s->securityPrivProto = usmAES256PrivProtocol;
 +		s->securityPrivProtoLen = OIDSIZE(usmAES256PrivProtocol);
  #endif
  #endif
  -		}
 +	if (netsnmp_session_set_security(session, a1, a2, a3, a4, a5, a6, a7)) {
 +		/* Warning message sent already, just bail out */
 +		RETURN_FALSE;
 +	} else {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown security protocol '%s'", prot);
 +		return (-1);
   	}
 -	return (-1);
 +	RETURN_TRUE;
  }
  /* }}} */
  
 -/* {{{ int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass)
 -   Make key from pass phrase in the snmpv3 session */
 -static int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass TSRMLS_DC)
 +/* {{{ proto mixed snmp2_get(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Fetch a SNMP object */
 +PHP_FUNCTION(snmp2_get)
 -	return (-1);
 +	return (0);
  }
  /* }}} */
  
 @@ -1060,31 +1126,15 @@
     Make key from pass phrase in the snmpv3 session */
  static int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass TSRMLS_DC)
   {
  -	/*
  -	 * make master key from pass phrases 
  -	 */
  -	if ((s) && (pass) && strlen(pass)) {
  -		s->securityAuthKeyLen = USM_AUTH_KU_LEN;
 -		if (s->securityAuthProto == NULL) {
 -		if (s->securityAuthProto == NULL) {
  -			/* get .conf set default */
  -			const oid *def = get_default_authtype(&(s->securityAuthProtoLen));
  -			s->securityAuthProto = snmp_duplicate_objid(def, s->securityAuthProtoLen);
  -		}


  -		if (generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
  -				(u_char *) pass, strlen(pass),
  -				s->securityAuthKey, &(s->securityAuthKeyLen)) != SNMPERR_SUCCESS) {
  -			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for authentication pass phrase");
 -			return (-2);
 -		}
 -		return (0);
 -	}
 -			return (-2);
 -		}
 -		return (0);
 +	int snmp_errno;
 +	s->securityAuthKeyLen = USM_AUTH_KU_LEN;
 +	if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
 +			(u_char *) pass, strlen(pass),
 +			s->securityAuthKey, &(s->securityAuthKeyLen)))) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for authentication pass phrase '%s': %s", pass, snmp_api_errstring(snmp_errno));
 +		return (-1);
  	}
  -	return (-1);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_2c);
 +	return (0);
   }
   /* }}} */
   
 -/* {{{ int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass)
 -   Make key from pass phrase in the snmpv3 session */
 -static int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass TSRMLS_DC)
 +/* {{{ proto mixed snmp2_real_get(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Fetch a SNMP object */
 +PHP_FUNCTION(snmp2_real_get)
 @@ -1092,241 +1142,449 @@
     Make key from pass phrase in the snmpv3 session */
  static int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass TSRMLS_DC)
   {
  -	if ((s) && (pass) && strlen(pass)) {
  -		s->securityPrivKeyLen = USM_PRIV_KU_LEN;
  -		if (s->securityPrivProto == NULL) {


  -			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for privacy pass phrase");
  -			return (-2);
  -		}
  -		return (0);
 -	}
 +	int snmp_errno;
 +
 +	s->securityPrivKeyLen = USM_PRIV_KU_LEN;
 +	if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
 +			pass, strlen(pass),
 +			s->securityPrivKey, &(s->securityPrivKeyLen)))) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for privacy pass phrase '%s': %s", pass, snmp_api_errstring(snmp_errno));
 +		return (-2);
  	}
  -	return (-1);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_GET | SNMP_ASSOC_OUTPUT), SNMP_VERSION_2c);
 +	return (0);
   }
   /* }}} */
   
  -/* {{{ proto string snmp2_get(string host, string community, string object_id [, int timeout [, int retries]]) 
 +/* {{{ proto mixed snmp2_getnext(string host, string community, mixed object_id [, int timeout [, int retries]]) 
     Fetch a SNMP object */
 -   Fetch a SNMP object */
  -PHP_FUNCTION(snmp2_get)
 +PHP_FUNCTION(snmp2_getnext)
 +/* {{{ in netsnmp_session_set_contextEngineID(struct snmp_session *s, u_char * contextEngineID) */
 +static int netsnmp_session_set_contextEngineID(struct snmp_session *s, u_char * contextEngineID)
   {
  -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_2c);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_2c);
  }
  /* }}} */
  
 -}
 -/* }}} */
 +	size_t	ebuf_len = 32, eout_len = 0;
 +	u_char	*ebuf = (u_char *) malloc(ebuf_len); /* memory freed by SNMP library, strdup NOT estrdup */
  
  -/* {{{ proto string snmp2_getnext(string host, string community, string object_id [, int timeout [, int retries]]) 
 +/* {{{ proto mixed snmp2_real_getnext(string host, string community, mixed object_id [, int timeout [, int retries]]) 
     Fetch a SNMP object */
 -   Fetch a SNMP object */
  -PHP_FUNCTION(snmp2_getnext)
 +PHP_FUNCTION(snmp2_real_getnext)
  {
 -{
  -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_2c);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_GETNEXT | SNMP_ASSOC_OUTPUT), SNMP_VERSION_2c);
 +	if (ebuf == NULL) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "malloc failure setting contextEngineID");
 +		return (-1);
 +	}
 +	if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, contextEngineID)) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad engine ID value '%s'", contextEngineID);
 +		free(ebuf);
 +		return (-1);
 +	}
 +	s->contextEngineID = ebuf;
 +	s->contextEngineIDLen = eout_len;
 +	return (0);
   }
   /* }}} */
  
  
  -/* {{{ proto array snmp2_walk(string host, string community, string object_id [, int timeout [, int retries]]) 
 +/* {{{ proto mixed snmp2_walk(string host, string community, mixed object_id [, int timeout [, int retries]]) 
     Return all objects under the specified object id */
  PHP_FUNCTION(snmp2_walk)
  {
 -   Return all objects under the specified object id */
 -PHP_FUNCTION(snmp2_walk)
 -{
  -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_2c);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_2c);
  }
  /* }}} */
 -}
 -/* }}} */
 +/* {{{ php_set_security */
   
  -/* {{{ proto array snmp2_real_walk(string host, string community, string object_id [, int timeout [, int retries]])
 +/* {{{ proto mixed snmp2_real_walk(string host, string community, mixed object_id [, int timeout [, int retries]])
     Return all objects including their respective object id withing the specified one */
  PHP_FUNCTION(snmp2_real_walk)
 -   Return all objects including their respective object id withing the specified one */
 -PHP_FUNCTION(snmp2_real_walk)
 +static int netsnmp_session_set_security(struct snmp_session *session, char *sec_level, char *auth_protocol, char *auth_passphrase, char *priv_protocol, char *priv_passphrase, char *contextName, char *contextEngineID)
   {
  -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_2c);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_ASSOC_OUTPUT), SNMP_VERSION_2c);
  }
  /* }}} */
 -}
 -/* }}} */
   
  -/* {{{ proto int snmp2_set(string host, string community, string object_id, string type, mixed value [, int timeout [, int retries]]) 
 +/* {{{ proto bool snmp2_set(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) 
     Set the value of a SNMP object */
  PHP_FUNCTION(snmp2_set)
  {
 -   Set the value of a SNMP object */
 -PHP_FUNCTION(snmp2_set)
 -{
  -	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_SET, SNMP_VERSION_2c);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_2c);
 +	/* Setting the security level. */
 +	if (netsnmp_session_set_sec_level(session, sec_level)) {
 +		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security level '%s'", sec_level);
 +		return (-1);
 +	}
 +
 +	if (session->securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
 +
 +		/* Setting the authentication protocol. */
 +		if (netsnmp_session_set_auth_protocol(session, auth_protocol)) {
 +			/* Warning message sent already, just bail out */
 +			return (-1);
 +		}
 +
 +		/* Setting the authentication passphrase. */
 +		if (netsnmp_session_gen_auth_key(session, auth_passphrase)) {
 +			/* Warning message sent already, just bail out */
 +			return (-1);
 +		}
 +
 +		if (session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
 +			/* Setting the security protocol. */
 +			if (netsnmp_session_set_sec_protocol(session, priv_protocol)) {
 +				/* Warning message sent already, just bail out */
 +				return (-1);
 +			}
 +
 +			/* Setting the security protocol passphrase. */
 +			if (netsnmp_session_gen_sec_key(session, priv_passphrase)) {
 +				/* Warning message sent already, just bail out */
 +				return (-1);
 +			}
 +		}
 +	}
 +
 +	/* Setting contextName if specified */
 +	if (contextName) {
 +		session->contextName = contextName;
 +		session->contextNameLen = strlen(contextName);
 +	}
 +
 +	/* Setting contextEngineIS if specified */
 +	if (contextEngineID && strlen(contextEngineID) && netsnmp_session_set_contextEngineID(session, contextEngineID)) {
 +		/* Warning message sent already, just bail out */
 +		return (-1);
 +	}
 +
 +	return (0);
   }
   /* }}} */
   
  -/* {{{ proto void php_snmpv3(INTERNAL_FUNCTION_PARAMETERS, int st)
  -*
  -* Generic SNMPv3 object fetcher
  -* From here is passed on the the common internal object fetcher.
 -*
 +/* {{{ php_snmp
  *
  -* st=SNMP_CMD_GET   snmp3_get() - query an agent and return a single value.
  -* st=SNMP_CMD_GETNEXT   snmp3_getnext() - query an agent and return the next single value.
  -* st=SNMP_CMD_WALK   snmp3_walk() - walk the mib and return a single dimensional array 
  -*                       containing the values.
  -* st=SNMP_CMD_REALWALK   snmp3_real_walk() - walk the mib and return an 
  -*                            array of oid,value pairs.
  -* st=SNMP_CMD_SET  snmp3_set() - query an agent and set a single value
 -*
 -*/
 +* Generic community based SNMP handler for all versions.
 +* This function makes use of the internal SNMP object fetcher.
  *
  */
  -static void php_snmpv3(INTERNAL_FUNCTION_PARAMETERS, int st)
 +/* {{{ proto mixed snmp3_get(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
 +   Fetch the value of a SNMP object */
 +PHP_FUNCTION(snmp3_get)
 +static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
   {
  -	char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
  -	int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len, a8_len;
  -	struct snmp_session session;
 -	long timeout = SNMP_DEFAULT_TIMEOUT;
 -	long retries = SNMP_DEFAULT_RETRIES;
 +	zval **oid, **value, **type;
 +	char *a1, *a2, *a3, *a4, *a5, *a6, *a7;
 +	int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len;
  	long timeout = SNMP_DEFAULT_TIMEOUT;
  	long retries = SNMP_DEFAULT_RETRIES;
  -	char type = (char) 0;
  -	char *value = (char *) 0, *stype = "";
  -	int stype_len, value_len;	
  -	char hostname[MAX_NAME_LEN];
  -	int remote_port = 161;
  -	char *pptr;
 -	int argc = ZEND_NUM_ARGS();
 +	int non_repeaters = 0;
 +	int max_repetitions = 20;
  	int argc = ZEND_NUM_ARGS();
  -	
  -	if (st == SNMP_CMD_SET) {	
  -		if (zend_parse_parameters(argc TSRMLS_CC, "ssssssssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
  -			&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &a8, &a8_len, &stype, &stype_len, &value, &value_len, &timeout, &retries) == FAILURE) {
 -			return;
 -		}
 -	} else {
 -			return;
 +	struct objid_set objid_set;
 +	php_snmp_session *session;
 +	int session_less_mode = (getThis() == NULL);
 +	int valueretrieval = SNMP_G(valueretrieval);
 +	php_snmp_object *snmp_object;
 +	php_snmp_object glob_snmp_object;
 +
 +	if (session_less_mode) {
 +		if (version == SNMP_VERSION_3) {
 +			if (st & SNMP_CMD_SET) {
 +				if (zend_parse_parameters(argc TSRMLS_CC, "sssssssZZZ|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 +					&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &oid, &type, &value, &timeout, &retries) == FAILURE) {
 +					RETURN_FALSE;
 +				}
 +			} else {
 +				/* SNMP_CMD_GET
 +				 * SNMP_CMD_GETNEXT
 +				 * SNMP_CMD_WALK
 +				 */
 +				if (zend_parse_parameters(argc TSRMLS_CC, "sssssssZ|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 +					&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &oid, &timeout, &retries) == FAILURE) {
 +					RETURN_FALSE;
 +				}
 +			}
 +		} else {
 +			if (st & SNMP_CMD_SET) {
 +				if (zend_parse_parameters(argc TSRMLS_CC, "ssZZZ|ll", &a1, &a1_len, &a2, &a2_len, &oid, &type, &value, &timeout, &retries) == FAILURE) {
 +					RETURN_FALSE;
 +				}
 +			} else {
 +				/* SNMP_CMD_GET
 +				 * SNMP_CMD_GETNEXT
 +				 * SNMP_CMD_WALK
 +				 */
 +				if (zend_parse_parameters(argc TSRMLS_CC, "ssZ|ll", &a1, &a1_len, &a2, &a2_len, &oid, &timeout, &retries) == FAILURE) {
 +					RETURN_FALSE;
 +				}
 +			}
  		}
  	} else {
  -		/* SNMP_CMD_GET
  -		 * SNMP_CMD_GETNEXT
  -		 * SNMP_CMD_WALK
  -		 * SNMP_CMD_REALWALK
  -		 */
  -		if (zend_parse_parameters(argc TSRMLS_CC, "ssssssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
  -			&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &a8, &a8_len, &timeout, &retries) == FAILURE) {
  -			return;
 -		}
 -	}
 -
 +		if (st & SNMP_CMD_SET) {
 +			if (zend_parse_parameters(argc TSRMLS_CC, "ZZZ", &oid, &type, &value) == FAILURE) {
 +				RETURN_FALSE;
 +			}
 +		} else if (st & SNMP_CMD_WALK) {
 +			if (zend_parse_parameters(argc TSRMLS_CC, "Z|ll", &oid, &non_repeaters, &max_repetitions) == FAILURE) {
 +				RETURN_FALSE;
 +			}
 +		} else {
 +			/* SNMP_CMD_GET
 +			 * SNMP_CMD_GETNEXT
 +			 */
 +			if (zend_parse_parameters(argc TSRMLS_CC, "Z", &oid) == FAILURE) {
 +				RETURN_FALSE;
 +			}
  		}
  	}
  
  -	snmp_sess_init(&session);
  -	/* This is all SNMPv3 */
  -	session.version = SNMP_VERSION_3;
  -


  -
  -	/* Setting the security name. */
  -	if (netsnmp_session_set_sec_name(&session, a2)) {
  -		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could net set security name: %s", a2);
 -		RETURN_FALSE;
 -	}
 -
 +	if (!php_snmp_parse_oid(st, &objid_set, oid, type, value)) {
  		RETURN_FALSE;
  	}
  
  -	/* Setting the security level. */
  -	if (netsnmp_session_set_sec_level(&session, a3 TSRMLS_CC)) {
  -		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security level: %s", a3);
 -		RETURN_FALSE;
 -	}
 -
 -		RETURN_FALSE;
 -	}
 -
  -	/* Setting the authentication protocol. */
  -	if (netsnmp_session_set_auth_protocol(&session, a4 TSRMLS_CC)) {
  -		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid authentication protocol: %s", a4);
 -		RETURN_FALSE;
 -	}
 -
 -		RETURN_FALSE;
 -	}
 -
  -	/* Setting the authentication passphrase. */
  -	if (netsnmp_session_gen_auth_key(&session, a5 TSRMLS_CC)) {
  -		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not generate key for authentication pass phrase: %s", a5);
 -		RETURN_FALSE;
 -		RETURN_FALSE;
  -	}
  -
  -	/* Setting the security protocol. */
  -	if (netsnmp_session_set_sec_protocol(&session, a6 TSRMLS_CC) && a6_len) {
  -		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security protocol: %s", a6);
 -		RETURN_FALSE;
 -	}
 -
 -		RETURN_FALSE;
 +	if (session_less_mode) {
 +		if (netsnmp_session_init(&session, version, a1, a2, timeout, retries)) {
 +			RETURN_FALSE;
 +		}
 +		if (version == SNMP_VERSION_3 && netsnmp_session_set_security(session, a3 TSRMLS_CC, a4 TSRMLS_CC, a5 TSRMLS_CC, a6 TSRMLS_CC, a7 TSRMLS_CC, NULL, NULL)) {
 +			/* Warning message sent already, just bail out */
 +			RETURN_FALSE;
 +		}
 +	} else {
 +		zval *object = getThis();
 +		PHP_SNMP_SESSION_FROM_OBJECT(session, object);
 +		snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 +		valueretrieval = snmp_object->valueretrieval;
 +#ifdef HAVE_NET_SNMP
 +		glob_snmp_object.enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
 +		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, snmp_object->enum_print);
 +		glob_snmp_object.quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
 +		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, snmp_object->quick_print);
 +		glob_snmp_object.oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 +		netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, snmp_object->oid_output_format);
 +#else
 +		glob_snmp_object.quick_print = snmp_get_quick_print();
 +		snmp_set_quick_print(snmp_object->quick_print);
 +#endif
  	}
  
  -	/* Setting the security protocol passphrase. */
  -	if (netsnmp_session_gen_sec_key(&session, a7 TSRMLS_CC) && a7_len) {
  -		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not generate key for security pass phrase: %s", a7);
  -		RETURN_FALSE;
  -	}
 -
 +	php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, session, &objid_set, non_repeaters, max_repetitions, valueretrieval);
  
  -	if (st == SNMP_CMD_SET) {
  -		type = stype[0];
 -	}
 +	if (session_less_mode) {
 +		netsnmp_session_free(&session);
 +	} else {
 +#ifdef HAVE_NET_SNMP
 +		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, glob_snmp_object.enum_print);
 +		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, glob_snmp_object.quick_print);
 +		netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, glob_snmp_object.oid_output_format);
 +#else
 +		snmp_set_quick_print(glob_snmp_object.quick_print);
 +#endif
  	}
  -
  -	session.retries = retries;
  -	session.timeout = timeout;
  -
  -	php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session, a8, type, value);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_3);
   }
   /* }}} */
   
  -/* {{{ proto int snmp3_get(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
 +/* {{{ proto mixed snmp3_real_get(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
     Fetch the value of a SNMP object */
 -   Fetch the value of a SNMP object */
  -PHP_FUNCTION(snmp3_get)
 +PHP_FUNCTION(snmp3_real_get)
 +/* {{{ proto mixed snmpget(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Fetch a SNMP object */
 +PHP_FUNCTION(snmpget)
   {
  -	php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_GET | SNMP_ASSOC_OUTPUT), SNMP_VERSION_3);
  }
  /* }}} */
  
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_1);
  }
  /* }}} */
  
  -/* {{{ proto int snmp3_getnext(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
 +/* {{{ proto mixed snmp3_getnext(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
     Fetch the value of a SNMP object */
  PHP_FUNCTION(snmp3_getnext)
 -   Fetch the value of a SNMP object */
 -PHP_FUNCTION(snmp3_getnext)
 +/* {{{ proto mixed snmpgetnext(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Fetch a SNMP object */
 +PHP_FUNCTION(snmpgetnext)
   {
  -	php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_3);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmp3_real_getnext(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
 +   Fetch the value of a SNMP object */
 +PHP_FUNCTION(snmp3_real_getnext)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_GETNEXT | SNMP_ASSOC_OUTPUT), SNMP_VERSION_3);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_1);
   }
   /* }}} */
   
  -/* {{{ proto int snmp3_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
 +/* {{{ proto mixed snmp3_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
     Fetch the value of a SNMP object */
  PHP_FUNCTION(snmp3_walk)
 -   Fetch the value of a SNMP object */
 -PHP_FUNCTION(snmp3_walk)
 +/* {{{ proto mixed snmpwalk(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Return all objects under the specified object id */
 +PHP_FUNCTION(snmpwalk)
   {
  -	php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_3);
  }
  /* }}} */
  
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_1);
  }
  /* }}} */
  
  -/* {{{ proto int snmp3_real_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
 +/* {{{ proto mixed snmp3_real_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
     Fetch the value of a SNMP object */
  PHP_FUNCTION(snmp3_real_walk)
 -   Fetch the value of a SNMP object */
 -PHP_FUNCTION(snmp3_real_walk)
 +/* {{{ proto mixed snmprealwalk(string host, string community, mixed object_id [, int timeout [, int retries]])
 +   Return all objects including their respective object id withing the specified one */
 +PHP_FUNCTION(snmprealwalk)
   {
  -	php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_REALWALK);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_ASSOC_OUTPUT), SNMP_VERSION_3);
  }
  /* }}} */
  
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_1);
  }
  /* }}} */
  
  -/* {{{ proto int snmp3_set(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id, string type, mixed value [, int timeout [, int retries]])
 +/* {{{ proto bool snmp3_set(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id, mixed type, mixed value [, int timeout [, int retries]])
     Fetch the value of a SNMP object */
  PHP_FUNCTION(snmp3_set)
 -   Fetch the value of a SNMP object */
 -PHP_FUNCTION(snmp3_set)
 +/* {{{ proto bool snmpset(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) 
 +   Set the value of a SNMP object */
 +PHP_FUNCTION(snmpset)
   {
  -	php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_3);
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_1);
   }
   /* }}} */
   
  -/* {{{ proto void snmp_set_valueretrieval(int method)
 +/* {{{ proto bool snmp_set_valueretrieval(int method)
     Specify the method how the SNMP values will be returned */
  PHP_FUNCTION(snmp_set_valueretrieval)
  {
  	long method;
  
  	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
 -		return;
 +		RETURN_FALSE;
  	}
  
  	if ((method == SNMP_VALUE_LIBRARY) || (method == SNMP_VALUE_PLAIN) || (method == SNMP_VALUE_OBJECT)) {
  		SNMP_G(valueretrieval) = method;
  	}
 +	RETURN_TRUE;
  }
  /* }}} */
  
 @@ -1326,7 +1746,7 @@
  }
  /* }}} */
 -   Specify the method how the SNMP values will be returned */
 -PHP_FUNCTION(snmp_set_valueretrieval)
 +/* {{{ proto bool snmp_get_quick_print(void)
 +   Return the current status of quick_print */
 +PHP_FUNCTION(snmp_get_quick_print)
  {
 -	long method;
 -
 -	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
 +	if (zend_parse_parameters_none() == FAILURE) {
  		return;
  	}
  
 -	if ((method == SNMP_VALUE_LIBRARY) || (method == SNMP_VALUE_PLAIN) || (method == SNMP_VALUE_OBJECT)) {
 -		SNMP_G(valueretrieval) = method;
 -	}
 +#ifdef HAVE_NET_SNMP
 +	RETURN_BOOL(netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT));
 +#else
 +	RETURN_BOOL(snmp_get_quick_print());
 +#endif
  }
  /* }}} */
  
 -/* {{{ proto int snmp_get_valueretrieval()
 -   Return the method how the SNMP values will be returned */
 +/* {{{ proto bool snmp_set_quick_print(int quick_print)
 +   Return all objects including their respective object id withing the specified one */
 +PHP_FUNCTION(snmp_set_quick_print)
 +{
 +	long a1;
 +
 +	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 +		RETURN_FALSE;
 +	}
 +
 +#ifdef HAVE_NET_SNMP
 +	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, (int)a1);
 +#else
 +	snmp_set_quick_print((int)a1);
 +#endif
 +	RETURN_TRUE;
 +}
 +/* }}} */
 +
 +#ifdef HAVE_NET_SNMP
 +/* {{{ proto bool snmp_set_enum_print(int enum_print)
 +   Return all values that are enums with their enum value instead of the raw integer */
 +PHP_FUNCTION(snmp_set_enum_print)
 +{
 +	long a1;
 +
 +	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 +		RETURN_FALSE;
 +	}
 +
 +	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, (int) a1);
 +	RETURN_TRUE;
 +} 
 +/* }}} */
 +
 +/* {{{ proto bool snmp_set_oid_output_format(int oid_format)
 +   Set the OID output format. */
 +PHP_FUNCTION(snmp_set_oid_output_format)
 +{
 +	long a1;
 +
 +	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 +		RETURN_FALSE;
 +	}
 +
 +	switch((int) a1) {
 +		case NETSNMP_OID_OUTPUT_SUFFIX:
 +		case NETSNMP_OID_OUTPUT_MODULE:
 +		case NETSNMP_OID_OUTPUT_FULL:
 +		case NETSNMP_OID_OUTPUT_NUMERIC:
 +		case NETSNMP_OID_OUTPUT_UCD:
 +		case NETSNMP_OID_OUTPUT_NONE:
 +			netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, a1);
 +			RETURN_TRUE;
 +			break;
 +		default:
 +			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP output print format '%d'", (int) a1);
 +			RETURN_FALSE;
 +			break;
 +	}
 +} 
 +/* }}} */
 +#endif
 +
 +/* {{{ proto mixed snmp2_get(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Fetch a SNMP object */
 +PHP_FUNCTION(snmp2_get)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_2c);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmp2_getnext(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Fetch a SNMP object */
 +PHP_FUNCTION(snmp2_getnext)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_2c);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmp2_walk(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 +   Return all objects under the specified object id */
 +PHP_FUNCTION(snmp2_walk)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_2c);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmp2_real_walk(string host, string community, mixed object_id [, int timeout [, int retries]])
 +   Return all objects including their respective object id withing the specified one */
 +PHP_FUNCTION(snmp2_real_walk)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_2c);
 +}
 +/* }}} */
 +
 +/* {{{ proto bool snmp2_set(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) 
 +   Set the value of a SNMP object */
 +PHP_FUNCTION(snmp2_set)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_2c);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmp3_get(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
 +   Fetch the value of a SNMP object */
 +PHP_FUNCTION(snmp3_get)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_3);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmp3_getnext(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
 +   Fetch the value of a SNMP object */
 +PHP_FUNCTION(snmp3_getnext)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_3);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmp3_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
 +   Fetch the value of a SNMP object */
 +PHP_FUNCTION(snmp3_walk)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_3);
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed snmp3_real_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
 +   Fetch the value of a SNMP object */
 +PHP_FUNCTION(snmp3_real_walk)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_3);
 +}
 +/* }}} */
 +
 +/* {{{ proto bool snmp3_set(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id, mixed type, mixed value [, int timeout [, int retries]])
 +   Fetch the value of a SNMP object */
 +PHP_FUNCTION(snmp3_set)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_3);
 +}
 +/* }}} */
 +
 +/* {{{ proto bool snmp_set_valueretrieval(int method)
 +   Specify the method how the SNMP values will be returned */
 +PHP_FUNCTION(snmp_set_valueretrieval)
 +{
 +	long method;
 +
 +	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
 +		RETURN_FALSE;
 +	}
 +
 +	switch(method) {
 +		case SNMP_VALUE_LIBRARY:
 +		case SNMP_VALUE_PLAIN:
 +		case SNMP_VALUE_OBJECT:
 +			SNMP_G(valueretrieval) = method;
 +			RETURN_TRUE;
 +			break;
 +		default:
 +			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP value retrieval method '%d'", method);
 +			RETURN_FALSE;
 +	}
 +}
 +/* }}} */
 +
 +/* {{{ proto int snmp_get_valueretrieval()
 +   Return the method how the SNMP values will be returned */
  PHP_FUNCTION(snmp_get_valueretrieval)
  {
  	RETURN_LONG(SNMP_G(valueretrieval));
  }
  /* }}} */
   
  -/* {{{ proto int snmp_read_mib(string filename)
  +/* {{{ proto bool snmp_read_mib(string filename)
      Reads and parses a MIB file into the active MIB tree. */
   PHP_FUNCTION(snmp_read_mib)
   {
 @@ -1334,12 +1754,9 @@
 @@ -1334,12 +1592,9 @@
   	int filename_len;
   
   	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
  -		return;
  +		RETURN_FALSE;
   	}
  
  
  -	/* Prevent read_mib() from printing any errors. */
  -	snmp_disable_stderrlog();
  -	
   	if (!read_mib(filename)) {
   		char *error = strerror(errno);
   		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading MIB file '%s': %s", filename, error);
 @@ -1349,6 +1604,605 @@
  }
  /* }}} */
  
 +/* {{{ proto SNMP SNMP::open(int version, string hostname, string community|securityName [, long timeout [, long retries]])
 +	Creates a new SNMP session to specified host. */
 +PHP_METHOD(snmp, open)
 +{
 +	php_snmp_object *snmp_object;
 +	zval *object = getThis();
 +	char *a1, *a2;
 +	int a1_len, a2_len;
 +	long timeout = SNMP_DEFAULT_TIMEOUT;
 +	long retries = SNMP_DEFAULT_RETRIES;
 +	int version = SNMP_DEFAULT_VERSION;
 +	int argc = ZEND_NUM_ARGS();
 +#if PHP_VERSION_ID > 50300
 +	zend_error_handling error_handling;
 +#endif
 +
 +	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 +#if PHP_VERSION_ID > 50300
 +	zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
 +#else
 +	php_set_error_handling(EH_THROW, zend_exception_get_default(TSRMLS_C) TSRMLS_CC);
 +#endif
 +	
 +	if (zend_parse_parameters(argc TSRMLS_CC, "lss|ll", &version, &a1, &a1_len, &a2, &a2_len, &timeout, &retries) == FAILURE) {
 +#if PHP_VERSION_ID > 50300
 +		zend_restore_error_handling(&error_handling TSRMLS_CC);
 +#else
 +		php_std_error_handling();
 +#endif
 +		return;
 +	}
 +
 +#if PHP_VERSION_ID > 50300
 +	zend_restore_error_handling(&error_handling TSRMLS_CC);
 +#else
 +	php_std_error_handling();
 +#endif
 +
 +	switch(version) {
 +		case SNMP_VERSION_1:
 +		case SNMP_VERSION_2c:
 +		case SNMP_VERSION_3:
 +			break;
 +		default:
 +			zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Unknown SNMP protocol version", 0 TSRMLS_CC);
 +			return;
 +	}
 +
 +	if (netsnmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries)) {
 +		return;
 +	}
 +	snmp_object->valueretrieval = SNMP_G(valueretrieval);
 +#ifdef HAVE_NET_SNMP
 +	snmp_object->enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
 +	snmp_object->oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 +	snmp_object->quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
 +#else
 +	snmp_object->quick_print = snmp_get_quick_print();
 +#endif
 +}
 +/* }}} */
 +
 +/* {{{ proto bool SNMP::close() 
 +	Close SNMP session */
 +PHP_METHOD(snmp, close)
 +{
 +	php_snmp_object *snmp_object;
 +	zval *object = getThis();
 +
 +	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 +
 +	if (zend_parse_parameters_none() == FAILURE) {
 +		RETURN_FALSE;
 +	}
 +
 +	netsnmp_session_free(&(snmp_object->session));
 +
 +	RETURN_TRUE;
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed SNMP::get_assoc(mixed object_id) 
 +   Fetch a SNMP object returing scalar for single OID and array of oid->value pairs for multi OID request */
 +PHP_METHOD(snmp, get)
 +{
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, (-1));
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed SNMP::getnext(mixed object_id) 
 +   Fetch a SNMP object returing scalar for single OID and array of oid->value pairs for multi OID request */
 +PHP_METHOD(snmp, getnext)
 +{
 +	zval *object = getThis();
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, (-1));
 +}
 +/* }}} */
 +
 +/* {{{ proto mixed SNMP::walk(mixed object_id)
 +   Return all objects including their respective object id withing the specified one as array of oid->value pairs */
 +PHP_METHOD(snmp, walk)
 +{
 +	zval *object = getThis();
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, (-1));
 +}
 +/* }}} */
 +
 +/* {{{ proto bool SNMP::set(mixed object_id, mixed type, mixed value) 
 +   Set the value of a SNMP object */
 +PHP_METHOD(snmp, set)
 +{
 +	zval *object = getThis();
 +	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, (-1));
 +}
 +
 +/* {{{ proto bool SNMP::set_security(resource session, string sec_level, [ string auth_protocol, string auth_passphrase [, string priv_protocol, string priv_passphrase [, string contextName [, string contextEngineID]]]])
 +	Set SNMPv3 security-related session parameters */
 +PHP_METHOD(snmp, set_security)
 +{
 +	php_snmp_object *snmp_object;
 +	zval *object = getThis();
 +	char *a1 = "", *a2 = "", *a3 = "", *a4 = "", *a5 = "", *a6 = "", *a7 = "";
 +	int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len;
 +	int argc = ZEND_NUM_ARGS();
 +
 +	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 +	
 +	if (zend_parse_parameters(argc TSRMLS_CC, "s|ssssss", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 +		&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len) == FAILURE) {
 +		RETURN_FALSE;
 +	}
 +
 +	if (netsnmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7)) {
 +		/* Warning message sent already, just bail out */
 +		RETURN_FALSE;
 +	}
 +	RETURN_TRUE;
 +}
 +/* }}} */
 +
 +/* {{{ */
 +void php_snmp_add_property(HashTable *h, const char *name, size_t name_length, php_snmp_read_t read_func, php_snmp_write_t write_func TSRMLS_DC)
 +{
 +	php_snmp_prop_handler p;
 +
 +	p.name = (char*) name;
 +	p.name_length = name_length;
 +	p.read_func = (read_func) ? read_func : NULL;
 +	p.write_func = (write_func) ? write_func : NULL;
 +	zend_hash_add(h, (char *)name, name_length + 1, &p, sizeof(php_snmp_prop_handler), NULL);
 +}
 +/* }}} */
 +
 +/* {{{ */
 +zval *php_snmp_read_property(zval *object, zval *member, int type TSRMLS_DC)
 +{
 +	zval tmp_member;
 +	zval *retval;
 +	php_snmp_object *obj;
 +	php_snmp_prop_handler *hnd;
 +	int ret;
 +
 +	ret = FAILURE;
 +	obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
 +
 +	if (Z_TYPE_P(member) != IS_STRING) {
 +		tmp_member = *member;
 +		zval_copy_ctor(&tmp_member);
 +		convert_to_string(&tmp_member);
 +		member = &tmp_member;
 +	}
 +
 +	ret = zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
 +
 +	if (ret == SUCCESS && hnd->read_func) {
 +		ret = hnd->read_func(obj, &retval TSRMLS_CC);
 +		if (ret == SUCCESS) {
 +			/* ensure we're creating a temporary variable */
 +			Z_SET_REFCOUNT_P(retval, 0);
 +		} else {
 +			retval = EG(uninitialized_zval_ptr);
 +		}
 +	} else {
 +		zend_object_handlers * std_hnd = zend_get_std_object_handlers();
 +		retval = std_hnd->read_property(object, member, type TSRMLS_CC);
 +	}
 +
 +	if (member == &tmp_member) {
 +		zval_dtor(member);
 +	}
 +	return(retval);
 +}
 +/* }}} */
 +
 +/* {{{ */
 +void php_snmp_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
 +{
 +	zval tmp_member;
 +	php_snmp_object *obj;
 +	php_snmp_prop_handler *hnd;
 +	int ret;
 +
 +	if (Z_TYPE_P(member) != IS_STRING) {
 +		tmp_member = *member;
 +		zval_copy_ctor(&tmp_member);
 +		convert_to_string(&tmp_member);
 +		member = &tmp_member;
 +	}
 +
 +	ret = FAILURE;
 +	obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
 +
 +	ret = zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **) &hnd);
 +
 +	if (ret == SUCCESS && hnd->write_func) {
 +		hnd->write_func(obj, value TSRMLS_CC);
 +		if (! PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) == 0) {
 +			Z_ADDREF_P(value);
 +			zval_ptr_dtor(&value);
 +		}
 +	} else {
 +		zend_object_handlers * std_hnd = zend_get_std_object_handlers();
 +		std_hnd->write_property(object, member, value TSRMLS_CC);
 +	}
 +
 +	if (member == &tmp_member) {
 +		zval_dtor(member);
 +	}
 +}
 +/* }}} */
 +
 +/* {{{ */
 +static int php_snmp_has_property(zval *object, zval *member, int has_set_exists TSRMLS_DC)
 +{
 +	php_snmp_object *obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
 +	php_snmp_prop_handler *hnd;
 +	int ret = 0;
 +
 +	if (zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **)&hnd) == SUCCESS) {
 +		switch (has_set_exists) {
 +			case 2:
 +				ret = 1;
 +				break;
 +			case 0: {
 +				zval *value = php_snmp_read_property(object, member, BP_VAR_IS TSRMLS_CC);
 +				if (value != EG(uninitialized_zval_ptr)) {
 +					ret = Z_TYPE_P(value) != IS_NULL? 1:0;
 +					/* refcount is 0 */
 +					Z_ADDREF_P(value);
 +					zval_ptr_dtor(&value);
 +				}
 +				break;
 +			}
 +			default: {
 +				zval *value = php_snmp_read_property(object, member, BP_VAR_IS TSRMLS_CC);
 +				if (value != EG(uninitialized_zval_ptr)) {
 +					convert_to_boolean(value);
 +					ret = Z_BVAL_P(value)? 1:0;
 +					/* refcount is 0 */
 +					Z_ADDREF_P(value);
 +					zval_ptr_dtor(&value);
 +				}
 +				break;
 +			}
 +		}
 +	} else {
 +		zend_object_handlers * std_hnd = zend_get_std_object_handlers();
 +		ret = std_hnd->has_property(object, member, has_set_exists TSRMLS_CC);
 +	}
 +	return ret;
 +}
 +/* }}} */
 +
 +/* {{{ */
 +static HashTable *php_snmp_get_properties(zval *object TSRMLS_DC)
 +{
 +	php_snmp_object *obj;
 +	php_snmp_prop_handler *hnd;
 +	HashTable *props;
 +	zval *val;
 +	char *key;
 +	uint key_len;
 +	HashPosition pos;
 +	ulong num_key;
 +
 +	obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
 +	props = obj->zo.properties;
 +
 +	zend_hash_internal_pointer_reset_ex(&php_snmp_properties, &pos);
 +
 +	while (zend_hash_get_current_data_ex(&php_snmp_properties, (void**)&hnd, &pos) == SUCCESS) {
 +		zend_hash_get_current_key_ex(&php_snmp_properties, &key, &key_len, &num_key, 0, &pos);
 +		MAKE_STD_ZVAL(val);
 +		if (!hnd->read_func || hnd->read_func(obj, &val TSRMLS_CC) != SUCCESS) {
 +			val = EG(uninitialized_zval_ptr);
 +		}
 +		zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
 +		zend_hash_move_forward_ex(&php_snmp_properties, &pos);
 +	}
 +	return obj->zo.properties;
 +}
 +/* }}} */
 +
 +/* {{{ */
 +static int php_snmp_read_valueretrieval(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
 +{
 +	MAKE_STD_ZVAL(*retval);
 +	ZVAL_LONG(*retval, snmp_object->valueretrieval);
 +	return SUCCESS;
 +}
 +/* }}} */
 +
 +/* {{{ */
 +static int php_snmp_read_quick_print(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
 +{
 +	MAKE_STD_ZVAL(*retval);
 +	ZVAL_BOOL(*retval, snmp_object->quick_print);
 +	return SUCCESS;
 +}
 +/* }}} */
 +
 +#ifdef HAVE_NET_SNMP
 +/* {{{ */
 +static int php_snmp_read_enum_print(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
 +{
 +	MAKE_STD_ZVAL(*retval);
 +	ZVAL_BOOL(*retval, snmp_object->enum_print);
 +	return SUCCESS;
 +}
 +/* }}} */
 +
 +/* {{{ */
 +static int php_snmp_read_oid_output_format(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
 +{
 +	MAKE_STD_ZVAL(*retval);
 +	ZVAL_LONG(*retval, snmp_object->oid_output_format);
 +	return SUCCESS;
 +}
 +/* }}} */
 +#endif
 +
 +/* {{{ */
 +static int php_snmp_write_valueretrieval(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 +{
 +	zval ztmp;
 +	int ret = SUCCESS;
 +	if (Z_TYPE_P(newval) != IS_LONG) {
 +		ztmp = *newval;
 +		zval_copy_ctor(&ztmp);
 +		convert_to_long(&ztmp);
 +		newval = &ztmp;
 +	}
 +
 +	switch(Z_LVAL_P(newval)) {
 +		case SNMP_VALUE_LIBRARY:
 +		case SNMP_VALUE_PLAIN:
 +		case SNMP_VALUE_OBJECT:
 +			snmp_object->valueretrieval = Z_LVAL_P(newval);
 +			break;
 +		default:
 +			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP value retrieval method '%d'", Z_LVAL_P(newval));
 +			ret = FAILURE;
 +			break;
 +	}
 +	
 +	if (newval == &ztmp) {
 +		zval_dtor(newval);
 +	}
 +
 +	return ret;
 +}
 +/* }}} */
 +
 +/* {{{ */
 +static int php_snmp_write_quick_print(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 +{
 +	zval ztmp;
 +	if (Z_TYPE_P(newval) != IS_BOOL) {
 +		ztmp = *newval;
 +		zval_copy_ctor(&ztmp);
 +		convert_to_boolean(&ztmp);
 +		newval = &ztmp;
 +	}
 +	
 +	snmp_object->quick_print = Z_LVAL_P(newval);
 +
 +	if (newval == &ztmp) {
 +		zval_dtor(newval);
 +	}
 +	return SUCCESS;
 +}
 +/* }}} */
 +
 +#ifdef HAVE_NET_SNMP
 +/* {{{ */
 +static int php_snmp_write_enum_print(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 +{
 +	zval ztmp;
 +	if (Z_TYPE_P(newval) != IS_BOOL) {
 +		ztmp = *newval;
 +		zval_copy_ctor(&ztmp);
 +		convert_to_boolean(&ztmp);
 +		newval = &ztmp;
 +	}
 +
 +	snmp_object->enum_print = Z_LVAL_P(newval);
 +	
 +	if (newval == &ztmp) {
 +		zval_dtor(newval);
 +	}
 +	return SUCCESS;
 +}
 +/* }}} */
 +
 +/* {{{ */
 +static int php_snmp_write_oid_output_format(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 +{
 +	zval ztmp;
 +	int ret = SUCCESS;
 +	if (Z_TYPE_P(newval) != IS_LONG) {
 +		ztmp = *newval;
 +		zval_copy_ctor(&ztmp);
 +		convert_to_long(&ztmp);
 +		newval = &ztmp;
 +	}
 +	
 +	switch(Z_LVAL_P(newval)) {
 +		case NETSNMP_OID_OUTPUT_SUFFIX:
 +		case NETSNMP_OID_OUTPUT_MODULE:
 +		case NETSNMP_OID_OUTPUT_FULL:
 +		case NETSNMP_OID_OUTPUT_NUMERIC:
 +		case NETSNMP_OID_OUTPUT_UCD:
 +		case NETSNMP_OID_OUTPUT_NONE:
 +			snmp_object->oid_output_format = Z_LVAL_P(newval);
 +			break;
 +		default:
 +			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP output print format '%d'", Z_LVAL_P(newval));
 +			ret = FAILURE;
 +			break;
 +	}
 +
 +	if (newval == &ztmp) {
 +		zval_dtor(newval);
 +	}
 +	return ret;
 +}
 +/* }}} */
 +#endif
 +
 +/* {{{ */
 +static zend_function_entry php_snmp_class_methods[] = {
 +	PHP_ME(snmp,	 open,				arginfo_snmp_open,		ZEND_ACC_PUBLIC)
 +	PHP_ME(snmp,	 close,				arginfo_snmp_void,		ZEND_ACC_PUBLIC)
 +	PHP_ME(snmp,	 set_security,			arginfo_snmp_set_security,	ZEND_ACC_PUBLIC)
 +
 +	PHP_ME(snmp,	 get,				arginfo_snmp_get,		ZEND_ACC_PUBLIC)
 +	PHP_ME(snmp,	 getnext,			arginfo_snmp_get,		ZEND_ACC_PUBLIC)
 +	PHP_ME(snmp,	 walk,				arginfo_snmp_walk,		ZEND_ACC_PUBLIC)
 +	PHP_ME(snmp,	 set,				arginfo_snmp_set,		ZEND_ACC_PUBLIC)
 +
 +	PHP_MALIAS(snmp, __construct,	open,		arginfo_snmp_open,		ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
 +	{NULL, NULL, NULL}
 +};
 +
 +#define PHP_SNMP_PROPERTY_ENTRY_RECORD(name) \
 +	{ "" #name "",		sizeof("" #name "") - 1,	php_snmp_read_##name,	php_snmp_write_##name }
 +
 +const php_snmp_prop_handler php_snmp_property_entries[] = {
 +	PHP_SNMP_PROPERTY_ENTRY_RECORD(valueretrieval),
 +	PHP_SNMP_PROPERTY_ENTRY_RECORD(quick_print),
 +#ifdef HAVE_NET_SNMP
 +	PHP_SNMP_PROPERTY_ENTRY_RECORD(enum_print),
 +	PHP_SNMP_PROPERTY_ENTRY_RECORD(oid_output_format),
 +#endif
 +	{ NULL, 0, NULL, NULL}
 +};
 +
 +/* {{{ PHP_MINIT_FUNCTION
 + */
 +PHP_MINIT_FUNCTION(snmp)
 +{
 +	netsnmp_log_handler *logh;
 +	zend_class_entry ce;
 +
 +	le_snmp_session = zend_register_list_destructors_ex(php_snmp_session_destructor, NULL, PHP_SNMP_SESSION_RES_NAME, module_number);
 +
 +	init_snmp("snmpapp");
 +
 +#ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
 +	/* Prevent update of the snmpapp.conf file */
 +	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
 +#endif
 +
 +	/* Disable logging, use exit status'es and related variabled to detect errors */
 +	shutdown_snmp_logging();
 +	logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_NONE, LOG_ERR);
 +	if (logh) {
 +		logh->pri_max = LOG_ERR;
 +	}
 +
 +	memcpy(&php_snmp_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
 +	php_snmp_object_handlers.read_property = php_snmp_read_property;
 +	php_snmp_object_handlers.write_property = php_snmp_write_property;
 +	php_snmp_object_handlers.has_property = php_snmp_has_property;
 +	php_snmp_object_handlers.get_properties = php_snmp_get_properties;
 +
 +	/* Register SNMP Class */
 +	INIT_CLASS_ENTRY(ce, "SNMP", php_snmp_class_methods);
 +	ce.create_object = php_snmp_object_new;
 +	php_snmp_object_handlers.clone_obj = NULL;
 +	php_snmp_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 +
 +	/* Register SNMP Class properties */
 +	zend_hash_init(&php_snmp_properties, 0, NULL, NULL, 1);
 +	PHP_SNMP_ADD_PROPERTIES(&php_snmp_properties, php_snmp_property_entries);
 +
 +#ifdef HAVE_NET_SNMP
 +	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_SUFFIX", NETSNMP_OID_OUTPUT_SUFFIX, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_MODULE", NETSNMP_OID_OUTPUT_MODULE, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_FULL", NETSNMP_OID_OUTPUT_FULL, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NUMERIC", NETSNMP_OID_OUTPUT_NUMERIC, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_UCD", NETSNMP_OID_OUTPUT_UCD, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NONE", NETSNMP_OID_OUTPUT_NONE, CONST_CS | CONST_PERSISTENT);
 +#endif
 +
 +	REGISTER_LONG_CONSTANT("SNMP_VALUE_LIBRARY", SNMP_VALUE_LIBRARY, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_VALUE_PLAIN", SNMP_VALUE_PLAIN, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_VALUE_OBJECT", SNMP_VALUE_OBJECT, CONST_CS | CONST_PERSISTENT);
 +
 +	REGISTER_LONG_CONSTANT("SNMP_BIT_STR", ASN_BIT_STR, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_OCTET_STR", ASN_OCTET_STR, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_OPAQUE", ASN_OPAQUE, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_NULL", ASN_NULL, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_OBJECT_ID", ASN_OBJECT_ID, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_IPADDRESS", ASN_IPADDRESS, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_COUNTER", ASN_GAUGE, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_UNSIGNED", ASN_UNSIGNED, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_TIMETICKS", ASN_TIMETICKS, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_UINTEGER", ASN_UINTEGER, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_INTEGER", ASN_INTEGER, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_COUNTER64", ASN_COUNTER64, CONST_CS | CONST_PERSISTENT);
 +
 +	REGISTER_LONG_CONSTANT("SNMP_VERSION_1", SNMP_VERSION_1, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_VERSION_2c", SNMP_VERSION_2c, CONST_CS | CONST_PERSISTENT);
 +	REGISTER_LONG_CONSTANT("SNMP_VERSION_3", SNMP_VERSION_3, CONST_CS | CONST_PERSISTENT);
 +
 +	return SUCCESS;
 +}
 +/* }}} */
 +
 +/* {{{ PHP_MSHUTDOWN_FUNCTION
 + */
 +PHP_MSHUTDOWN_FUNCTION(snmp)
 +{
 +	snmp_shutdown("snmpapp");
 +	
 +	zend_hash_destroy(&php_snmp_properties);
 +
 +	return SUCCESS;
 +}
 +/* }}} */
 +
 +/* {{{ PHP_MINFO_FUNCTION
 + */
 +PHP_MINFO_FUNCTION(snmp)
 +{
 +	php_info_print_table_start();
 +#ifdef HAVE_NET_SNMP
 +	php_info_print_table_row(2, "NET-SNMP Support", "enabled");
 +	php_info_print_table_row(2, "NET-SNMP Version", netsnmp_get_version());
 +#else
 +	php_info_print_table_row(2, "UCD-SNMP Support", "enabled");
 +	php_info_print_table_row(2, "UCD-SNMP Version", VersionInfo);
 +#endif
 +	php_info_print_table_row(2, "PHP SNMP Version", PHP_SNMP_VERSION);
 +	php_info_print_table_end();
 +}
 +/* }}} */
 +
 +/* {{{ snmp_module_entry
 + */
 +zend_module_entry snmp_module_entry = {
 +	STANDARD_MODULE_HEADER,
 +	"snmp",
 +	snmp_functions,
 +	PHP_MINIT(snmp),
 +	PHP_MSHUTDOWN(snmp),
 +	NULL,
 +	NULL,
 +	PHP_MINFO(snmp),
 +	PHP_SNMP_VERSION,
 +	PHP_MODULE_GLOBALS(snmp),
 +	PHP_GINIT(snmp),
 +	NULL,
 +	NULL,
 +	STANDARD_MODULE_PROPERTIES_EX
 +};
 +/* }}} */
 +
  #endif
  
  /*
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 02:01:28 2024 UTC