Hi,

as promised I've created a patch which adds some functionality to the 
SNMP module. It's controlled with a new function named 
snmp_set_valuemethod(int method) which changes the way how SNMP values 
are returned by snmpget(), snmpwalk() and snmpwalkoid(). The following 
(new) constants can be passed to snmp_set_valuemethod():
- SNMP_VALUEMETHOD_LIBRARY:
  Values will be retrieved with snprint_value() from the net-snmp
  library, so they will be hard to parse as it may add quotes to
  strings, pre-parse timeticks, etc. (old/default behaviour)
- SNMP_VALUEMETHOD_PLAIN:
  Value will be processed internally depending on the value type;
  no pre-parsing will occur and the values will be returned as
  they are sent by the SNMP agent. Note however, that all values
  (even numbers) will be strings, as most numbers will exceed
  the PHP 32-bit signed limit!
- SNMP_VALUEMETHOD_OBJECT:
  Values will be returned as objects with two properties named
  "value" and "type"; "value" will contain the value as returned
  with SNMP_VALUEMETHOD_PLAIN and "type" will contain the type
  as returned by the net-snmp library, which will enable you to
  do things depending on the value type returned by the SNMP
  agent (the ASN_* constants from the net-snmp library are also
  defined as PHP constants)

All this is achieved via a new internal C function named 
php_snmp_getvalue(). The default behaviour is 100% compatible with the old 
one. I've tried hard to change as less as possible in the existing source 
code. However I had to introduce a global variable named 
snmp_globals->valuemethod (via TSRM of course).

A new function named snmp_get_valuemethod() has also been created. It 
simply returns the current method.

The patch makes it much easier to parse the returned SNMP values, as they 
are no longer pre-parsed by the net-snmp library after you have set 
SNMP_VALUEMETHOD_PLAIN. I've attached a simple PHP script which should 
make the new functionality even clearer.

Cheers, Jonny <[EMAIL PROTECTED]>

? snmp-valuemethod.patch
Index: ext/snmp/php_snmp.h
===================================================================
RCS file: /repository/php4/ext/snmp/php_snmp.h,v
retrieving revision 1.16
diff -u -r1.16 php_snmp.h
--- ext/snmp/php_snmp.h 31 Dec 2002 16:07:27 -0000      1.16
+++ ext/snmp/php_snmp.h 14 Jan 2003 18:40:06 -0000
@@ -16,6 +16,7 @@
 |          Mike Jackson <[EMAIL PROTECTED]>                            |
 |          Steven Lawrance <[EMAIL PROTECTED]>                |
 |          Harrie Hazewinkel <[EMAIL PROTECTED]>                      |
+|          Johann Hanne <[EMAIL PROTECTED]>                               |
 +----------------------------------------------------------------------+
 */
 
@@ -31,6 +32,10 @@
 extern zend_module_entry snmp_module_entry;
 #define snmp_module_ptr &snmp_module_entry
 
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
 PHP_MINIT_FUNCTION(snmp);
 PHP_FUNCTION(snmpget);
 PHP_FUNCTION(snmpwalk);
@@ -46,7 +51,22 @@
 PHP_FUNCTION(snmp3_real_walk);
 PHP_FUNCTION(snmp3_set);
 //PHP_FUNCTION(snmp3_getbulk);
+
+PHP_FUNCTION(snmp_set_valuemethod);
+PHP_FUNCTION(snmp_get_valuemethod);
+
 PHP_MINFO_FUNCTION(snmp);
+
+ZEND_BEGIN_MODULE_GLOBALS(snmp)
+       int valuemethod;
+ZEND_END_MODULE_GLOBALS(snmp)
+
+#ifdef ZTS
+#define SNMP_G(v) TSRMG(snmp_globals_id, zend_snmp_globals *, v)
+#else
+#define SNMP_G(v) (snmp_globals.v)
+#endif
+
 #else
 
 #define snmp_module_ptr NULL
Index: ext/snmp/snmp.c
===================================================================
RCS file: /repository/php4/ext/snmp/snmp.c,v
retrieving revision 1.73
diff -u -r1.73 snmp.c
--- ext/snmp/snmp.c     31 Dec 2002 16:07:28 -0000      1.73
+++ ext/snmp/snmp.c     14 Jan 2003 18:40:06 -0000
@@ -16,6 +16,7 @@
 |          Mike Jackson <[EMAIL PROTECTED]>                            |
 |          Steven Lawrance <[EMAIL PROTECTED]>                |
 |          Harrie Hazewinkel <[EMAIL PROTECTED]>                      |
+|          Johann Hanne <[EMAIL PROTECTED]>                               |
 +----------------------------------------------------------------------+
 */
 /* $Id: snmp.c,v 1.73 2002/12/31 16:07:28 sebastian Exp $ */
@@ -108,6 +109,12 @@
 #define SNMP_MSG_GETNEXT GETNEXT_REQ_MSG
 #endif
 
+#define SNMP_VALUEMETHOD_LIBRARY       0
+#define SNMP_VALUEMETHOD_PLAIN         1
+#define SNMP_VALUEMETHOD_OBJECT                2
+
+ZEND_DECLARE_MODULE_GLOBALS(snmp)
+
 /* constant - can be shared among threads */
 static oid objid_mib[] = {1, 3, 6, 1, 2, 1};
 
@@ -130,6 +137,8 @@
        PHP_FE(snmp3_walk, NULL)
        PHP_FE(snmp3_real_walk, NULL)
        PHP_FE(snmp3_set, NULL)
+       PHP_FE(snmp_set_valuemethod, NULL)
+       PHP_FE(snmp_get_valuemethod, NULL)
        {NULL,NULL,NULL}
 };
 /* }}} */
@@ -156,11 +165,50 @@
 
 /* THREAD_LS snmp_module php_snmp_module; - may need one of these at some point */
 
+/* {{{ php_snmp_init_globals
+ */
+static void php_snmp_init_globals(zend_snmp_globals *snmp_globals)
+{
+       snmp_globals->valuemethod = 0;
+}
+/* }}} */
+
 /* {{{ PHP_MINIT_FUNCTION
  */
 PHP_MINIT_FUNCTION(snmp)
 {
        init_snmp("snmpapp");
+
+       ZEND_INIT_MODULE_GLOBALS(snmp, php_snmp_init_globals, NULL);
+
+       REGISTER_LONG_CONSTANT("SNMP_VALUEMETHOD_LIBRARY", SNMP_VALUEMETHOD_LIBRARY, 
+CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("SNMP_VALUEMETHOD_PLAIN", SNMP_VALUEMETHOD_PLAIN, 
+CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("SNMP_VALUEMETHOD_OBJECT", SNMP_VALUEMETHOD_OBJECT, 
+CONST_CS | CONST_PERSISTENT);
+
+       REGISTER_LONG_CONSTANT("ASN_BIT_STR", ASN_BIT_STR, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_OCTET_STR", ASN_OCTET_STR, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_OPAQUE", ASN_OPAQUE, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_NULL", ASN_NULL, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_OBJECT_ID", ASN_OBJECT_ID, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_IPADDRESS", ASN_IPADDRESS, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_COUNTER", ASN_GAUGE, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_UNSIGNED", ASN_UNSIGNED, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_TIMETICKS", ASN_TIMETICKS, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_UINTEGER", ASN_UINTEGER, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_INTEGER", ASN_INTEGER, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_COUNTER64", ASN_COUNTER64, CONST_CS | 
+CONST_PERSISTENT);
+#ifdef OPAQUE_SPECIAL_TYPES
+       REGISTER_LONG_CONSTANT("ASN_UNSIGNED64", ASN_UNSIGNED64, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_OPAQUE_COUNTER64", ASN_OPAQUE_COUNTER64, CONST_CS 
+| CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_OPAQUE_U64", ASN_OPAQUE_U64, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_INTEGER64", ASN_INTEGER64, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_OPAQUE_I64", ASN_OPAQUE_I64, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_FLOAT", ASN_FLOAT, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_OPAQUE_FLOAT", ASN_OPAQUE_FLOAT, CONST_CS | 
+CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_DOUBLE", ASN_DOUBLE, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ASN_OPAQUE_DOUBLE", ASN_OPAQUE_DOUBLE, CONST_CS | 
+CONST_PERSISTENT);
+#endif
+
        return SUCCESS;
 }
 /* }}} */
@@ -181,6 +229,154 @@
 }
 /* }}} */
 
+/* {{{ php_snmp_getvalue
+*
+* Gets the SNMP value from the variable_list structure (first parameter)
+* and puts it into a zval (second parameter)
+*
+* The method how the values will be pre-parsed and what will be put
+* into the zval depends on the global variable "valuemethod" which can
+* be set via the PHP function snmp_set_valuemethod():
+* - SNMP_VALUEMETHOD_LIBRARY:
+*   Values will be retrieved with snprint_value() from the net-snmp
+*   library, so they will be hard to parse as it may add quotes to
+*   strings, pre-parse timeticks, etc. (old/default behaviour)
+* - SNMP_VALUEMETHOD_PLAIN:
+*   Value will be processed internally depending on the value type;
+*   no pre-parsing will occur and the values will be returned as
+*   they are sent by the SNMP agent. Note however, that all values
+*   (even numbers) will be strings, as most numbers will exceed
+*   the PHP 32-bit signed limit!
+* - SNMP_VALUEMETHOD_OBJECT:
+*   Values will be returned as objects with two properties named
+*   "value" and "type"; "value" will contain the value as returned
+*   with SNMP_VALUEMETHOD_PLAIN and "type" will contain the type
+*   as returned by the net-snmp library, which will enable you to
+*   do things depending on the value type returned by the SNMP
+*   agent (the ASN_* constants from the net-snmp library are also
+*   defined as PHP constants)
+*
+*/
+static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_DC)
+{
+       zval *val;
+#if I64CHARSZ > 2047
+       char buf[I64CHARSZ + 1];
+#else
+       char buf[2048];
+#endif
+
+       if (SNMP_G(valuemethod) == SNMP_VALUEMETHOD_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
+
+               ZVAL_STRING(snmpval, buf, 1);
+               return;
+       }
+
+       MAKE_STD_ZVAL(val);
+
+       switch (vars->type) {
+       case ASN_BIT_STR:               /* 0x03, asn1.h */
+               ZVAL_STRINGL(val, vars->val.bitstring, vars->val_len, 1);
+               break;
+
+       case ASN_OCTET_STR:             /* 0x04, asn1.h */
+       case ASN_OPAQUE:                /* 0x44, snmp_impl.h */
+               ZVAL_STRINGL(val, vars->val.string, vars->val_len, 1);
+               break;
+
+       case ASN_NULL:                  /* 0x05, asn1.h */
+               ZVAL_NULL(val);
+               break;
+
+       case ASN_OBJECT_ID:             /* 0x06, asn1.h */
+#ifdef HAVE_NET_SNMP
+               snprint_objid(buf, sizeof(buf), vars->val.objid, vars->val_len / 
+sizeof(oid));
+#else
+               sprint_objid(buf, vars->val.objid, vars->val_len, vars->val_len / 
+sizeof(oid));
+#endif
+
+               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;
+               ZVAL_STRING(val, buf, 1);
+               break;
+
+       case ASN_COUNTER:               /* 0x41, snmp_impl.h */
+       case ASN_GAUGE:                 /* 0x42, snmp_impl.h */
+       /* 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, "%u", *vars->val.integer);
+               buf[sizeof(buf)-1]=0;
+               ZVAL_STRING(val, buf, 1);
+               break;
+
+       case ASN_INTEGER:               /* 0x02, asn1.h */
+               snprintf(buf, sizeof(buf)-1, "%d", *vars->val.integer);
+               buf[sizeof(buf)-1]=0;
+               ZVAL_STRING(val, buf, 1);
+               break;
+
+       case ASN_COUNTER64:             /* 0x46, snmp_impl.h */
+#ifdef OPAQUE_SPECIAL_TYPES
+       case ASN_UNSIGNED64:            /* 0x4b, snmp_impl.h */
+       case ASN_OPAQUE_COUNTER64:      /* 0x76, asn1.h */
+       case ASN_OPAQUE_U64:            /* 0x7b, asn1.h */
+#endif
+               printU64(buf, vars->val.counter64);
+               ZVAL_STRING(val, buf, 1);
+               break;
+
+#ifdef OPAQUE_SPECIAL_TYPES
+       case ASN_INTEGER64:             /* 0x4a, snmp_impl.h */
+       case ASN_OPAQUE_I64:            /* 0x7a, asn1.h */
+               printI64(buf, vars->val.counter64);
+               ZVAL_STRING(val, buf, 1);
+               break;
+#endif
+
+#ifdef OPAQUE_SPECIAL_TYPES
+       case ASN_FLOAT:                 /* 0x48, snmp_impl.h */
+       case ASN_OPAQUE_FLOAT:          /* 0x78, asn1.h */
+               snprintf(buf, sizeof(buf)-1, "%f", *vars->val.floatVal);
+               buf[sizeof(buf)-1]=0;
+               ZVAL_STRING(val, buf, 1);
+               break;
+
+       case ASN_DOUBLE:                /* 0x49, snmp_impl.h */
+       case ASN_OPAQUE_DOUBLE:         /* 0x79, asn1.h */
+               snprintf(buf, sizeof(buf)-1, "%e", *vars->val.doubleVal);
+               buf[sizeof(buf)-1]=0;
+               ZVAL_STRING(val, buf, 1);
+               break;
+#endif
+
+       default:
+               ZVAL_STRING(val, "Unknown value type", 1);
+               break;
+       }
+
+       if (SNMP_G(valuemethod) == SNMP_VALUEMETHOD_PLAIN) {
+               *snmpval = *val;
+               zval_copy_ctor(snmpval);
+       } else {
+               object_init(snmpval);
+               add_property_long(snmpval, "type", vars->type);
+               add_property_zval(snmpval, "value", val);
+       }
+}
+/* }}} */
+
 /* {{{ php_snmp_internal
 *
 * Generic SNMP object fetcher (for both v3 and v1)
@@ -214,6 +410,7 @@
        char type = (char) 0;
        char *value = (char *) 0;
        char *err;
+       zval *snmpval;
 
        if (st >= 2) { /* walk */
                rootlen = MAX_NAME_LEN;
@@ -287,24 +484,23 @@
                                        }
 
                                        if (st != 11) {
-#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
+                                               MAKE_STD_ZVAL(snmpval);
+                                               php_snmp_getvalue(vars, snmpval 
+TSRMLS_CC);
                                        }
 
                                        if (st == 1) {
-                                               RETVAL_STRING(buf,1);
+                                               *return_value = *snmpval;
+                                               zval_copy_ctor(return_value);
+                                               return;
                                        } else if (st == 2) {
-                                               
add_next_index_string(return_value,buf,1); /* Add to returned array */
+                                               
+add_next_index_zval(return_value,snmpval); /* Add to returned array */
                                        } else if (st == 3)  {
 #ifdef HAVE_NET_SNMP
                                                snprint_objid(buf2, sizeof(buf2), 
vars->name, vars->name_length);
 #else
                                                sprint_objid(buf2, vars->name, 
vars->name_length);
 #endif
-                                               
add_assoc_string(return_value,buf2,buf,1);
+                                               
+add_assoc_zval(return_value,buf2,snmpval);
                                        }
                                        if (st >= 2 && st != 11) {
                                                if (vars->type != SNMP_ENDOFMIBVIEW && 

@@ -870,6 +1066,34 @@
 PHP_FUNCTION(snmp3_set)
 {
        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, 11);
+}
+/* }}} */
+
+/* {{{ proto void snmp_set_valuemethod(int method)
+   Specify the method how the SNMP values will be returned */
+PHP_FUNCTION(snmp_set_valuemethod)
+{
+       zval **method;
+
+       if (ZEND_NUM_ARGS() != 1 ||
+               zend_get_parameters_ex(ZEND_NUM_ARGS(), &method) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(method);
+        if ((Z_LVAL_PP(method) == SNMP_VALUEMETHOD_LIBRARY) ||
+            (Z_LVAL_PP(method) == SNMP_VALUEMETHOD_PLAIN) ||
+            (Z_LVAL_PP(method) == SNMP_VALUEMETHOD_OBJECT)) {
+               SNMP_G(valuemethod) = Z_LVAL_PP(method);
+       }
+}
+/* }}} */
+
+/* {{{ proto int snmp_get_valuemethod()
+   Return the method how the SNMP values will be returned */
+PHP_FUNCTION(snmp_get_valuemethod)
+{
+       RETURN_LONG(SNMP_G(valuemethod));
 }
 /* }}} */
 
#!/usr/local/bin/php
<?php

$host="192.168.1.1";
$community="public";

print "Calling snmp_set_valuemethod(SNMP_VALUEMETHOD_LIBRARY)...\n";
snmp_set_valuemethod(SNMP_VALUEMETHOD_LIBRARY);
print "snmp_get_valuemethod() returns: ".snmp_get_valuemethod()."\n";
$uptime=snmpget($host, $community, ".1.3.6.1.2.1.1.3.0");
print "snmpget() returned: $uptime\n\n";

print "Calling snmp_set_valuemethod(SNMP_VALUEMETHOD_PLAIN)...\n";
snmp_set_valuemethod(SNMP_VALUEMETHOD_PLAIN);
print "snmp_get_valuemethod() returns: ".snmp_get_valuemethod()."\n";
$uptime=snmpget($host, $community, ".1.3.6.1.2.1.1.3.0");
print "snmpget() returned: $uptime\n\n";

print "Calling snmp_set_valuemethod(SNMP_VALUEMETHOD_OBJECT)...\n";
snmp_set_valuemethod(SNMP_VALUEMETHOD_OBJECT);
print "snmp_get_valuemethod() returns: ".snmp_get_valuemethod()."\n";
$uptime=snmpget($host, $community, ".1.3.6.1.2.1.1.3.0");
print "snmpget() returned: $uptime\n";
print_r($uptime);
print "\n";

print "Calling snmp_set_valuemethod(-123)...\n";
snmp_set_valuemethod(-123);
print "snmp_get_valuemethod() returns: ".snmp_get_valuemethod()."\n";

?>
-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to