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

Reply via email to