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