Hello,
>> I have modified snmpget and snmpgetnext to accept
>> mixed type object_id. It can be a string, specifying a single object_id, or
>> an
>> array of strings specifying multiple object_ids.
>>
>> The patch is against PHP 5.2.5. Please comment.
>
> The patch is missing, please use a .txt extension.
A patch attached with .txt extension.
--
Best Regards,
Leon
--- php-5.2.5-vanilla/ext/snmp/snmp.c 2007-07-09 15:42:05.000000000 +0200
+++ php-5.2.5/ext/snmp/snmp.c 2009-01-16 00:12:27.000000000 +0100
@@ -341,6 +341,101 @@
add_property_zval(snmpval, "value", val);
}
}
+/* }}} */
+
+/* {{{ php_snmp_add_var_to_pdu
+*
+* add an object_id into the SNMP PDU. The PDU can be a SNMP-GET, SNMP-GETNEXT
+*/
+static int php_snmp_add_var_to_pdu(struct snmp_pdu *pdu,
+ char *object_id)
+{
+ oid name[MAX_NAME_LEN];
+ size_t name_length;
+
+ name_length = MAX_OID_LEN;
+ if (!snmp_parse_oid(object_id, name, &name_length)) {
+ php_error_docref(NULL TSRMLS_CC,
+ E_WARNING,
+ "Invalid object identifier: %s",
+ object_id);
+ return FAILURE;
+ }
+
+ snmp_add_null_var(pdu, name, name_length);
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ php_snmp_add_array_to_pdu
+*
+* add all object_ids specified in the array into the SNMP PDU.
+*/
+static int php_snmp_add_array_to_pdu(struct snmp_pdu *pdu,
+ HashTable *array, int *vb_count)
+{
+ zval **val;
+ HashPosition pos;
+ int status;
+
+ *vb_count = 0;
+
+ zend_hash_internal_pointer_reset_ex(array, &pos);
+
+ while (zend_hash_get_current_data_ex(
+ array, (void **)&val, &pos) == SUCCESS) {
+
+ convert_to_string_ex (val);
+
+ status = php_snmp_add_var_to_pdu (pdu, Z_STRVAL_PP(val));
+ if (status != SUCCESS)
+ {
+ return FAILURE;
+ }
+
+ (*vb_count)++;
+ zend_hash_move_forward_ex(array, &pos);
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ php_snmp_add_vars_to_pdu
+*
+* Add object_id to the SNMP PDU. object_id can be a single or
+* multiple object_ids, specifed in array.
+*
+*/
+static int php_snmp_add_vars_to_pdu(struct snmp_pdu *pdu,
+ zval **objid,
+ int
*vb_count)
+{
+ int status;
+
+ switch (Z_TYPE_PP(objid))
+ {
+ case IS_STRING:
+ status = php_snmp_add_var_to_pdu (
+ pdu, Z_STRVAL_PP (objid));
+ *vb_count = 1;
+ break;
+ case IS_ARRAY:
+ status = php_snmp_add_array_to_pdu (
+ pdu, Z_ARRVAL_PP (objid), vb_count);
+ break;
+ default:
+ convert_to_string_ex (objid);
+ status = php_snmp_add_var_to_pdu (
+ pdu, Z_STRVAL_PP (objid));
+ *vb_count = 1;
+ break;
+ }
+
+ return status;
+}
+/* }}} */
/* {{{ php_snmp_internal
*
@@ -356,10 +451,10 @@
*
*/
static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st,
- struct snmp_session
*session,
- char *objid,
- char type,
- char* value)
+ struct snmp_session *session,
+ zval **objid,
+ char type,
+ char *value)
{
struct snmp_session *ss;
struct snmp_pdu *pdu=NULL, *response;
@@ -375,14 +470,26 @@
int keepwalking=1;
char *err;
zval *snmpval = NULL;
+ char *object_id = NULL;
+ int vb_count;
if (st >= SNMP_CMD_WALK) { /* walk */
+ /* walk supports string only objid */
+ if (IS_STRING != Z_TYPE_PP(objid)) {
+ php_error_docref(NULL TSRMLS_CC,
+ E_WARNING,
+ "object_id should be a string");
+ RETURN_FALSE;
+ }
+
+ object_id = Z_STRVAL_PP(objid);
+
rootlen = MAX_NAME_LEN;
- if (strlen(objid)) { /* on a walk, an empty string means top of
tree - no error */
- if (snmp_parse_oid(objid, root, &rootlen)) {
+ if (strlen(object_id)) { /* on a walk, an empty string means
top of tree - no error */
+ if (snmp_parse_oid(object_id, root, &rootlen)) {
gotroot = 1;
} 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", object_id);
}
}
@@ -418,13 +525,27 @@
keepwalking = 0;
if ((st == SNMP_CMD_GET) || (st == SNMP_CMD_GETNEXT)) {
pdu = snmp_pdu_create((st == SNMP_CMD_GET) ?
SNMP_MSG_GET : SNMP_MSG_GETNEXT);
- name_length = MAX_OID_LEN;
- if (!snmp_parse_oid(objid, name, &name_length)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Invalid object identifier: %s", objid);
+ vb_count = 0;
+ status = php_snmp_add_vars_to_pdu (pdu, objid,
&vb_count);
+ if (status != SUCCESS) {
snmp_close(ss);
RETURN_FALSE;
}
- snmp_add_null_var(pdu, name, name_length);
+
+ if (!vb_count) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "no object_id(s) specified in
array");
+ snmp_close(ss);
+ RETURN_FALSE;
+ }
+
+ /*
+ * if more than a single object_id was specified
+ * a return must be an array
+ */
+ if (vb_count > 1) {
+ array_init(return_value);
+ }
} else if (st == SNMP_CMD_SET) {
pdu = snmp_pdu_create(SNMP_MSG_SET);
if (snmp_add_var(pdu, name, name_length, type, value)) {
@@ -452,6 +573,7 @@
status = snmp_synch_response(ss, pdu, &response);
if (status == STAT_SUCCESS) {
if (response->errstat == SNMP_ERR_NOERROR) {
+ vb_count = count_varbinds (response->variables);
for (vars = response->variables; vars; vars =
vars->next_variable) {
if (st >= SNMP_CMD_WALK && st !=
SNMP_CMD_SET &&
(vars->name_length < rootlen ||
memcmp(root, vars->name, rootlen * sizeof(oid)))) {
@@ -464,16 +586,36 @@
}
if (st == SNMP_CMD_GET) {
- *return_value = *snmpval;
- zval_copy_ctor(return_value);
- zval_ptr_dtor(&snmpval);
- snmp_close(ss);
- return;
+ if (vb_count == 1) {
+ *return_value =
*snmpval;
+
zval_copy_ctor(return_value);
+ zval_ptr_dtor(&snmpval);
+ snmp_close(ss);
+ return;
+ } else {
+#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_zval(return_value, buf2, snmpval);
+ }
} else if (st == SNMP_CMD_GETNEXT) {
- *return_value = *snmpval;
- zval_copy_ctor(return_value);
- snmp_close(ss);
- return;
+ if (vb_count == 1) {
+ *return_value =
*snmpval;
+
zval_copy_ctor(return_value);
+ snmp_close(ss);
+ return;
+ } else {
+#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_zval(return_value, buf2,snmpval);
+ }
} else if (st == SNMP_CMD_WALK) {
add_next_index_zval(return_value,snmpval); /* Add to returned array */
} else if (st == SNMP_CMD_REALWALK) {
@@ -575,7 +717,8 @@
*/
static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
{
- zval **a1, **a2, **a3, **a4, **a5, **a6, **a7;
+ zval **z_hostname, **z_community, **z_oid, **z_type, **z_value;
+ zval **z_timeout, **z_retries;
struct snmp_session session;
long timeout=SNMP_DEFAULT_TIMEOUT;
long retries=SNMP_DEFAULT_RETRIES;
@@ -587,52 +730,57 @@
char *pptr;
if (myargc < 3 || myargc > 7 ||
- zend_get_parameters_ex(myargc, &a1, &a2, &a3, &a4, &a5, &a6,
&a7) == FAILURE) {
+ zend_get_parameters_ex(myargc,
+ &z_hostname,
+ &z_community,
+ &z_oid,
+ &z_type,
+ &z_value,
+ &z_timeout,
+ &z_retries) == FAILURE) {
WRONG_PARAM_COUNT;
}
- convert_to_string_ex(a1);
- convert_to_string_ex(a2);
- convert_to_string_ex(a3);
-
+ convert_to_string_ex(z_hostname);
+ convert_to_string_ex(z_community);
+
if (st == SNMP_CMD_SET) {
if (myargc < 5) {
WRONG_PARAM_COUNT;
}
- convert_to_string_ex(a4);
- convert_to_string_ex(a5);
+ convert_to_string_ex(z_type);
+ convert_to_string_ex(z_value);
if(myargc > 5) {
- convert_to_long_ex(a6);
- timeout = Z_LVAL_PP(a6);
+ convert_to_long_ex(z_timeout);
+ timeout = Z_LVAL_PP(z_timeout);
}
if(myargc > 6) {
- convert_to_long_ex(a7);
- retries = Z_LVAL_PP(a7);
+ convert_to_long_ex(z_retries);
+ retries = Z_LVAL_PP(z_retries);
}
- type = Z_STRVAL_PP(a4)[0];
- value = Z_STRVAL_PP(a5);
+ type = Z_STRVAL_PP(z_type)[0];
+ value = Z_STRVAL_PP(z_value);
} else {
if(myargc > 3) {
- convert_to_long_ex(a4);
- timeout = Z_LVAL_PP(a4);
+ convert_to_long_ex(z_timeout);
+ timeout = Z_LVAL_PP(z_timeout);
}
if(myargc > 4) {
- convert_to_long_ex(a5);
- retries = Z_LVAL_PP(a5);
+ convert_to_long_ex(z_retries);
+ retries = Z_LVAL_PP(z_retries);
}
}
snmp_sess_init(&session);
- strlcpy(hostname, Z_STRVAL_PP(a1), sizeof(hostname));
+ strlcpy(hostname, Z_STRVAL_PP(z_hostname), sizeof(hostname));
if ((pptr = strchr (hostname, ':'))) {
remote_port = strtol (pptr + 1, NULL, 0);
}
-
session.peername = hostname;
session.remote_port = remote_port;
session.version = version;
@@ -643,21 +791,24 @@
* memory it did not allocate
*/
#ifdef UCD_SNMP_HACK
- session.community = (u_char *)strdup(Z_STRVAL_PP(a2)); /* memory freed
by SNMP library, strdup NOT estrdup */
+ /* memory freed by SNMP library, strdup NOT estrdup */
+ session.community =
+ (u_char *)strdup(Z_STRVAL_PP(z_community));
#else
- session.community = (u_char *)Z_STRVAL_PP(a2);
+ session.community = (u_char *)Z_STRVAL_PP(z_community);
#endif
- session.community_len = Z_STRLEN_PP(a2);
+ session.community_len = Z_STRLEN_PP(z_community);
session.retries = retries;
session.timeout = timeout;
session.authenticator = NULL;
- php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session,
Z_STRVAL_PP(a3), type, value);
+ php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session,
+ z_oid, type, value);
}
/* }}} */
-/* {{{ proto string snmpget(string host, string community, string object_id [,
int timeout [, int retries]])
+/* {{{ proto string snmpget(string host, string community, mixed object_id [,
int timeout [, int retries]])
Fetch a SNMP object */
PHP_FUNCTION(snmpget)
{
@@ -1104,7 +1255,7 @@
session.retries = retries;
session.timeout = timeout;
- php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session,
Z_STRVAL_PP(a8), type, value);
+ php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session, a8,
type, value);
}
/* }}} */
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php