]> granicus.if.org Git - php/commitdiff
- Improved SNMP extension:
authorBoris Lytochkin <lytboris@php.net>
Tue, 1 Feb 2011 07:45:30 +0000 (07:45 +0000)
committerBoris Lytochkin <lytboris@php.net>
Tue, 1 Feb 2011 07:45:30 +0000 (07:45 +0000)
  . Allow ~infinite OIDs in GET/GETNEXT/SET queries. Autochunk them to max_oids
    upon request.

NEWS
ext/snmp/php_snmp.h
ext/snmp/snmp.c
ext/snmp/tests/snmp_parse_oid.phpt [deleted file]

diff --git a/NEWS b/NEWS
index 08dc6a1405a5fb46da8a1366857960fd125ecba4..8ab552fcb87cf0d2382254a7bf388201d0f137cb 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -200,9 +200,11 @@ PHP                                                                        NEWS
 - Improved SNMP extension:
   . Added OO API. FR #53594. 
   . Sanitized return values of existing functions. Now it returns FALSE on
-    failure
-  . Introducing unit tests for extension with ~full coverage
-  . Fixed bugs #44193, #44193, #45893, #46065, #51336, #53862
+    failure.
+  . Allow ~infinite OIDs in GET/GETNEXT/SET queries. Autochunk them to max_oids
+    upon request.
+  . Introducing unit tests for extension with ~full coverage.
+  . Fixed bugs #44193, #44193, #45893, #46065, #51336, #53862.
 
 ## UNSORTED ##
 
index a5d0055372002722ff7571b59af135588ae368b9..4cda3f8fc871e9e28e0e316b7d6df9c952108412 100644 (file)
@@ -83,6 +83,7 @@ PHP_METHOD(SNMP, set);
 typedef struct _php_snmp_object {
       zend_object zo;
       struct snmp_session *session;
+      int max_oids;
       int valueretrieval;
       int quick_print;
 #ifdef HAVE_NET_SNMP
index 74b45832d9b45da4bb73be160d8126612c47c468..93c27b9068b723501a67206e9b6ebd36d27e64d2 100644 (file)
@@ -405,13 +405,12 @@ typedef struct _snmpobjarg {
 
 } snmpobjarg;
 
-#define SNMP_MAXOIDS_IN_PDU 64
 struct objid_set {
        int count;
        int offset;
        int step;
        int array_output;
-       snmpobjarg vars[SNMP_MAXOIDS_IN_PDU];
+       snmpobjarg *vars;
 };
 
 /* {{{ snmp_functions[]
@@ -548,7 +547,7 @@ static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_D
                        buf = dbuf;
                        buflen = val_len;
                } else {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "malloc() failed: %s, fallback to static array", strerror(errno));
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed: %s, fallback to static array", strerror(errno));
                }
        }
 
@@ -931,6 +930,11 @@ static int php_snmp_parse_oid(int st, struct objid_set *objid_set, zval **oid, z
        objid_set->count = 0;
        objid_set->array_output = ((st & SNMP_CMD_WALK) ? TRUE : FALSE);
        if (Z_TYPE_PP(oid) == IS_STRING) {
+               objid_set->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg));
+               if (objid_set->vars == NULL) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while parsing oid: %s", strerror(errno));
+                       return FALSE;
+               }
                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) {
@@ -952,6 +956,11 @@ static int php_snmp_parse_oid(int st, struct objid_set *objid_set, zval **oid, z
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Got empty OID array");
                        return FALSE;
                }
+               objid_set->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_PP(oid)));
+               if (objid_set->vars == NULL) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno));
+                       return FALSE;
+               }
                objid_set->array_output = ( (st & SNMP_CMD_SET) ? FALSE : TRUE );
                for (   zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(oid), &pos_oid);
                        zend_hash_get_current_data_ex(Z_ARRVAL_PP(oid), (void **) &tmp_oid, &pos_oid) == SUCCESS;
@@ -992,11 +1001,7 @@ static int php_snmp_parse_oid(int st, struct objid_set *objid_set, zval **oid, z
                                        }
                                }
                        }
-
-                       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;
-                       }
+                       objid_set->count++;
                }
        }
 
@@ -1269,7 +1274,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
        long timeout = SNMP_DEFAULT_TIMEOUT;
        long retries = SNMP_DEFAULT_RETRIES;
        int non_repeaters = 0;
-       int max_repetitions = 20;
+       int max_repetitions = -1;
        int argc = ZEND_NUM_ARGS();
        struct objid_set objid_set;
        php_snmp_session *session;
@@ -1345,6 +1350,12 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
                zval *object = getThis();
                PHP_SNMP_SESSION_FROM_OBJECT(session, object);
                snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
+               if (snmp_object->max_oids > 0) {
+                       objid_set.step = snmp_object->max_oids;
+                       if (max_repetitions < 0) { // unspecified in function call, use session-wise
+                               max_repetitions = snmp_object->max_oids;
+                       }
+               }
                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);
@@ -1359,7 +1370,13 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 #endif
        }
 
+       if (max_repetitions < 0) {
+               max_repetitions = 20; // provide correct default value
+       }
+
        php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, session, &objid_set, non_repeaters, max_repetitions, valueretrieval);
+       
+       efree(objid_set.vars);
 
        if (session_less_mode) {
                netsnmp_session_free(&session);
@@ -1678,6 +1695,7 @@ PHP_METHOD(snmp, open)
        if (netsnmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries TSRMLS_CC)) {
                return;
        }
+       snmp_object->max_oids = 0;
        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);
@@ -1931,6 +1949,15 @@ static HashTable *php_snmp_get_properties(zval *object TSRMLS_DC)
 }
 /* }}} */
 
+/* {{{ */
+static int php_snmp_read_max_oids(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
+{
+       MAKE_STD_ZVAL(*retval);
+       ZVAL_LONG(*retval, snmp_object->max_oids);
+       return SUCCESS;
+}
+/* }}} */
+
 /* {{{ */
 static int php_snmp_read_valueretrieval(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
 {
@@ -1969,6 +1996,28 @@ static int php_snmp_read_oid_output_format(php_snmp_object *snmp_object, zval **
 /* }}} */
 #endif
 
+/* {{{ */
+static int php_snmp_write_max_oids(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;
+       }
+
+       snmp_object->max_oids = Z_LVAL_P(newval);
+       
+       if (newval == &ztmp) {
+               zval_dtor(newval);
+       }
+
+       return ret;
+}
+/* }}} */
+
 /* {{{ */
 static int php_snmp_write_valueretrieval(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 {
@@ -2096,6 +2145,7 @@ static zend_function_entry php_snmp_class_methods[] = {
        { "" #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(max_oids),
        PHP_SNMP_PROPERTY_ENTRY_RECORD(valueretrieval),
        PHP_SNMP_PROPERTY_ENTRY_RECORD(quick_print),
 #ifdef HAVE_NET_SNMP
diff --git a/ext/snmp/tests/snmp_parse_oid.phpt b/ext/snmp/tests/snmp_parse_oid.phpt
deleted file mode 100644 (file)
index e0017f5..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
---TEST--                                 
-Function snmp_parse_oid
---CREDITS--
-Boris Lytochkin
---SKIPIF--
-<?php
-require_once(dirname(__FILE__).'/skipif.inc');
-?>
---FILE--
-<?php
-require_once(dirname(__FILE__).'/snmp_include.inc');
-
-//EXPECTF format is quickprint OFF
-snmp_set_quick_print(false);
-snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
-
-$oid1 = 'SNMPv2-MIB::sysContact.0';
-$type1 = 's';
-$oldvalue1 = snmpget($hostname, $communityWrite, $oid1, $timeout, $retries);
-$newvalue1 = $oldvalue1 . '0';
-
-echo "Checking SNMP_MAXOIDS_IN_PDU\n";
-$i  = 0;
-$oids = array();
-while($i++ < 128){
-       $oids[] = '.1.3.6.1.2.1.1.7.0';
-}
-$z = snmp2_get($hostname, $community, $oids, $timeout, $retries);
-var_dump($z);
-
-?>
---EXPECTF--
-Checking SNMP_MAXOIDS_IN_PDU
-
-Warning: snmp2_get(): Could not process more than %d OIDs in singe GET/GETNEXT/SET query in %s on line %d
-bool(false)
\ No newline at end of file