lytboris                                 Wed, 31 Aug 2011 08:28:13 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=315862

Log:
more tuning based on discussion in FR #40816:
 * parse all OIDs earlier, detect all wrong OIDs before any query
   is made (GET-operations)
 * introduce ERRNO_MULTIPLE_SET_QUERIES:
    warn if request contains more OIDs than max_oids and SET operation
    (and type&value checks) will be done in chunks.
fix set method when request contains more OIDs than max_oids (2nd and
 subsequent chunk were ignored)

Bug: https://bugs.php.net/40816 (Feedback) Add "snmptranslate" function
      
Changed paths:
    U   php/php-src/trunk/ext/snmp/snmp.c
    U   php/php-src/trunk/ext/snmp/tests/snmp-object.phpt
    U   php/php-src/trunk/ext/snmp/tests/snmp3-error.phpt

Modified: php/php-src/trunk/ext/snmp/snmp.c
===================================================================
--- php/php-src/trunk/ext/snmp/snmp.c	2011-08-31 07:49:52 UTC (rev 315861)
+++ php/php-src/trunk/ext/snmp/snmp.c	2011-08-31 08:28:13 UTC (rev 315862)
@@ -118,6 +118,7 @@
 #define PHP_SNMP_ERRNO_ERROR_IN_REPLY	3
 #define PHP_SNMP_ERRNO_OID_NOT_INCREASING 4
 #define PHP_SNMP_ERRNO_OID_PARSING_ERROR 5
+#define PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES 6

 ZEND_DECLARE_MODULE_GLOBALS(snmp)
 static PHP_GINIT_FUNCTION(snmp);
@@ -685,11 +686,8 @@
 	struct snmp_session *ss;
 	struct snmp_pdu *pdu=NULL, *response;
 	struct variable_list *vars;
-	oid name[MAX_NAME_LEN];
-	size_t name_length;
 	oid root[MAX_NAME_LEN];
 	size_t rootlen = 0;
-	int gotroot = 0;
 	int status, count, found;
 	char buf[2048];
 	char buf2[2048];
@@ -704,35 +702,10 @@
 	/* reset errno and errstr */
 	php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_NOERROR, "");

-	if (st & SNMP_CMD_WALK) {
-		if (objid_query->count > 1) {
-			php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Multi OID walks are not supported!");
-			RETURN_FALSE;
-		}
-		rootlen = MAX_NAME_LEN;
-		if (strlen(objid_query->vars[0].oid)) { /* on a walk, an empty string means top of tree - no error */
-			if (snmp_parse_oid(objid_query->vars[0].oid, root, &rootlen)) {
-				gotroot = 1;
-			} else {
-				php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[0].oid);
-				RETVAL_FALSE;
-				return;
-			}
-		}
-
-		if (!gotroot) {
-			memmove((char *) root, (char *) objid_mib, sizeof(objid_mib));
-			rootlen = sizeof(objid_mib) / sizeof(oid);
-			gotroot = 1;
-		}
-
-		memmove((char *)name, (char *)root, rootlen * sizeof(oid));
-		name_length = rootlen;
+	if (st & SNMP_CMD_WALK) { /* remember root OID */
+		memmove((char *)root, (char *)(objid_query->vars[0].name), (objid_query->vars[0].name_length) * sizeof(oid));
+		rootlen = objid_query->vars[0].name_length;
 		objid_query->offset = objid_query->count;
-
-		memmove((char *)objid_query->vars[0].name, (char *)root, rootlen * sizeof(oid));
-		objid_query->vars[0].name_length = rootlen;
-
 	}

 	if ((ss = snmp_open(session)) == NULL) {
@@ -743,6 +716,10 @@
 		return;
 	}

+	if ((st & SNMP_CMD_SET) && objid_query->count > objid_query->step) {
+		php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES, "Can not fit all OIDs for SET query into one packet, using multiple queries");
+	}
+
 	while (keepwalking) {
 		keepwalking = 0;
 		if (st & SNMP_CMD_WALK) {
@@ -753,7 +730,7 @@
 				pdu->non_repeaters = objid_query->non_repeaters;
 				pdu->max_repetitions = objid_query->max_repetitions;
 			}
-			snmp_add_null_var(pdu, name, name_length);
+			snmp_add_null_var(pdu, objid_query->vars[0].name, objid_query->vars[0].name_length);
 		} else {
 			if (st & SNMP_CMD_GET) {
 				pdu = snmp_pdu_create(SNMP_MSG_GET);
@@ -768,14 +745,6 @@
 				return;
 			}
 			for (count = 0; objid_query->offset < objid_query->count && count < objid_query->step; objid_query->offset++, count++){
-				objid_query->vars[objid_query->offset].name_length = MAX_OID_LEN;
-				if (!snmp_parse_oid(objid_query->vars[objid_query->offset].oid, objid_query->vars[objid_query->offset].name, &(objid_query->vars[objid_query->offset].name_length))) {
-					php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[objid_query->offset].oid);
-					snmp_free_pdu(pdu);
-					snmp_close(ss);
-					RETVAL_FALSE;
-					return;
-				}
 				if (st & SNMP_CMD_SET) {
 					if ((snmp_errno = snmp_add_var(pdu, objid_query->vars[objid_query->offset].name, objid_query->vars[objid_query->offset].name_length, objid_query->vars[objid_query->offset].type, objid_query->vars[objid_query->offset].value))) {
 						snprint_objid(buf, sizeof(buf), objid_query->vars[objid_query->offset].name, objid_query->vars[objid_query->offset].name_length);
@@ -802,6 +771,10 @@
 		if (status == STAT_SUCCESS) {
 			if (response->errstat == SNMP_ERR_NOERROR) {
 				if (st & SNMP_CMD_SET) {
+					if (objid_query->offset < objid_query->count) { /* we have unprocessed OIDs */
+						keepwalking = 1;
+						continue;
+					}
 					snmp_free_pdu(response);
 					snmp_close(ss);
 					RETVAL_TRUE;
@@ -885,13 +858,13 @@

 					/* OID increase check */
 					if (st & SNMP_CMD_WALK) {
-						if (objid_query->oid_increasing_check == TRUE && snmp_oid_compare(name, name_length, vars->name, vars->name_length) >= 0) {
+						if (objid_query->oid_increasing_check == TRUE && snmp_oid_compare(objid_query->vars[0].name, objid_query->vars[0].name_length, vars->name, vars->name_length) >= 0) {
 							snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
 							php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_NOT_INCREASING, "Error: OID not increasing: %s", buf2);
 							keepwalking = 0;
 						} else {
-							memmove((char *)name, (char *)vars->name, vars->name_length * sizeof(oid));
-							name_length = vars->name_length;
+							memmove((char *)(objid_query->vars[0].name), (char *)vars->name, vars->name_length * sizeof(oid));
+							objid_query->vars[0].name_length = vars->name_length;
 							keepwalking = 1;
 						}
 					}
@@ -965,7 +938,7 @@
 * OID parser (and type, value for SNMP_SET command)
 */

-static int php_snmp_parse_oid(int st, struct objid_query *objid_query, zval **oid, zval **type, zval **value TSRMLS_DC)
+static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_query, zval **oid, zval **type, zval **value TSRMLS_DC)
 {
 	char *pptr;
 	HashPosition pos_oid, pos_type, pos_value;
@@ -1085,6 +1058,34 @@
 		}
 	}

+	/* now parse all OIDs */
+	if (st & SNMP_CMD_WALK) {
+		if (objid_query->count > 1) {
+			php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Multi OID walks are not supported!");
+			efree(objid_query->vars);
+			return FALSE;
+		}
+		objid_query->vars[0].name_length = MAX_NAME_LEN;
+		if (strlen(objid_query->vars[0].oid)) { /* on a walk, an empty string means top of tree - no error */
+			if (!snmp_parse_oid(objid_query->vars[0].oid, objid_query->vars[0].name, &(objid_query->vars[0].name_length))) {
+				php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[0].oid);
+				efree(objid_query->vars);
+				return FALSE;
+			}
+		} else {
+			memmove((char *)objid_query->vars[0].name, (char *)objid_mib, sizeof(objid_mib));
+			objid_query->vars[0].name_length = sizeof(objid_mib) / sizeof(oid);
+		}
+	} else {
+		for (objid_query->offset = 0; objid_query->offset < objid_query->count; objid_query->offset++) {
+			objid_query->vars[objid_query->offset].name_length = MAX_OID_LEN;
+			if (!snmp_parse_oid(objid_query->vars[objid_query->offset].oid, objid_query->vars[objid_query->offset].name, &(objid_query->vars[objid_query->offset].name_length))) {
+				php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[objid_query->offset].oid);
+				efree(objid_query->vars);
+				return FALSE;
+			}
+		}
+	}
 	objid_query->offset = 0;
 	objid_query->step = objid_query->count;
 	return (objid_query->count > 0);
@@ -1465,7 +1466,7 @@
 		}
 	}

-	if (!php_snmp_parse_oid(st, &objid_query, oid, type, value TSRMLS_CC)) {
+	if (!php_snmp_parse_oid(getThis(), st, &objid_query, oid, type, value TSRMLS_CC)) {
 		RETURN_FALSE;
 	}

@@ -2439,6 +2440,7 @@
 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_ERROR_IN_REPLY",		(long)PHP_SNMP_ERRNO_ERROR_IN_REPLY);
 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_OID_NOT_INCREASING",	(long)PHP_SNMP_ERRNO_OID_NOT_INCREASING);
 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_OID_PARSING_ERROR",	(long)PHP_SNMP_ERRNO_OID_PARSING_ERROR);
+	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_MULTIPLE_SET_QUERIES",	(long)PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES);

 	return SUCCESS;
 }

Modified: php/php-src/trunk/ext/snmp/tests/snmp-object.phpt
===================================================================
--- php/php-src/trunk/ext/snmp/tests/snmp-object.phpt	2011-08-31 07:49:52 UTC (rev 315861)
+++ php/php-src/trunk/ext/snmp/tests/snmp-object.phpt	2011-08-31 08:28:13 UTC (rev 315862)
@@ -122,6 +122,23 @@
 var_dump(($session->get($oid1) === $oldvalue1));
 var_dump($session->close());

+echo "Multiple OID with max_oids = 1\n";
+$oid2 = 'SNMPv2-MIB::sysLocation.0';
+$session = new SNMP(SNMP::VERSION_3, $hostname, $rwuser, $timeout, $retries);
+$session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', $priv_pass);
+$session->max_oids = 1;
+$oldvalue2 = $session->get($oid2);
+$newvalue2 = $oldvalue2 . '0';
+$z = $session->set(array($oid1, $oid2), array('s','s'), array($newvalue1, $newvalue2));
+var_dump($z);
+var_dump(($session->get($oid1) === $newvalue1));
+var_dump(($session->get($oid2) === $newvalue2));
+$z = $session->set(array($oid1, $oid2), array('s','s'), array($oldvalue1, $oldvalue2));
+var_dump($z);
+var_dump(($session->get($oid1) === $oldvalue1));
+var_dump(($session->get($oid2) === $oldvalue2));
+var_dump($session->close());
+
 echo "SNMPv3, setting contextEngineID (authPriv)\n";
 $session = new SNMP(SNMP::VERSION_3, $hostname, $rwuser, $timeout, $retries);
 $session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, '', 'aeeeff');
@@ -200,6 +217,18 @@
 bool(true)
 bool(true)
 bool(true)
+Multiple OID with max_oids = 1
+
+Warning: SNMP::set(): Can not fit all OIDs for SET query into one packet, using multiple queries in %s on line %d
+bool(true)
+bool(true)
+bool(true)
+
+Warning: SNMP::set(): Can not fit all OIDs for SET query into one packet, using multiple queries in %s on line %d
+bool(true)
+bool(true)
+bool(true)
+bool(true)
 SNMPv3, setting contextEngineID (authPriv)
 string(%d) "%S"
 bool(true)

Modified: php/php-src/trunk/ext/snmp/tests/snmp3-error.phpt
===================================================================
--- php/php-src/trunk/ext/snmp/tests/snmp3-error.phpt	2011-08-31 07:49:52 UTC (rev 315861)
+++ php/php-src/trunk/ext/snmp/tests/snmp3-error.phpt	2011-08-31 08:28:13 UTC (rev 315862)
@@ -17,14 +17,14 @@
 //              string object_id [, int timeout [, int retries]]);

 var_dump(snmp3_get($hostname, $community, '', '', '', '', ''));
-var_dump(snmp3_get($hostname, $community, '', '', '', '', '', ''));
-var_dump(snmp3_get($hostname, $community, 'bugusPriv', '', '', '', '', ''));
-var_dump(snmp3_get($hostname, $community, 'authNoPriv', 'TTT', '', '', '', ''));
-var_dump(snmp3_get($hostname, $community, 'authNoPriv', 'MD5', '', '', '', ''));
-var_dump(snmp3_get($hostname, $community, 'authNoPriv', 'MD5', 'te', '', '', ''));
-var_dump(snmp3_get($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'BBB', '', ''));
-var_dump(snmp3_get($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'AES', '', ''));
-var_dump(snmp3_get($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'AES', 'ty', ''));
+var_dump(snmp3_get($hostname, $community, '', '', '', '', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'bugusPriv', '', '', '', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authNoPriv', 'TTT', '', '', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authNoPriv', 'MD5', '', '', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authNoPriv', 'MD5', 'te', '', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'BBB', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'AES', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'AES', 'ty', '.1.3.6.1.2.1.1.1.0'));
 var_dump(snmp3_get($hostname, 'somebogususer', 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, '.1.3.6.1.2.1.1.1.0', $timeout, $retries));

 var_dump(snmp3_set($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, '', 's'));
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to