Commit 33e3966f8b2 for php.net

commit 33e3966f8b28564700dfe96509d47f3d54688bc7
Author: eskyuu <swilton@fluentit.au>
Date:   Mon Aug 24 21:08:31 2026 +0800

    snmp: Additional SNMP library output formatting options (#21502)

    RFC: https://wiki.php.net/rfc/snmp_improvements_2026#implement_more_mib_parsing_and_value_output_controls

diff --git a/ext/snmp/php_snmp.h b/ext/snmp/php_snmp.h
index c5376ee2e1b..52100b09b77 100644
--- a/ext/snmp/php_snmp.h
+++ b/ext/snmp/php_snmp.h
@@ -48,6 +48,13 @@ typedef struct _php_snmp_object {
 	int valueretrieval;
 	bool quick_print;
 	bool enum_print;
+	bool numeric_index;
+	bool numeric_timeticks;
+	bool extended_index;
+	bool dont_print_units;
+	bool escape_quotes;
+	bool print_hex_text;
+	int string_output_format;
 	int oid_output_format;
 	int snmp_errno;
 	bool oid_increasing_check;
diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c
index 8fac85a236a..94b7d803a03 100644
--- a/ext/snmp/snmp.c
+++ b/ext/snmp/snmp.c
@@ -22,6 +22,7 @@
 #endif

 #include "php.h"
+#include "Zend/zend_enum.h"
 #include "main/php_network.h"
 #include "ext/standard/info.h"

@@ -64,7 +65,12 @@
 #include <net-snmp/net-snmp-config.h>
 #include <net-snmp/net-snmp-includes.h>

+#include "snmp_decl.h"
 #include "snmp_arginfo.h"
+static zend_class_entry *SnmpMib_ce;
+static zend_class_entry *SnmpOidOutput_ce;
+static zend_class_entry *SnmpOutput_ce;
+static zend_class_entry *SnmpStringOutput_ce;

 /* For net-snmp prior to 5.4 */
 #ifndef HAVE_SHUTDOWN_SNMP_LOGGING
@@ -90,6 +96,10 @@ typedef struct snmp_session php_snmp_session;
 }

 static bool mib_needs_reset;
+static php_snmp_object saved_snmp_settings;
+static int saved_mib_allow_underscores;
+static int saved_mib_comment_term;
+static int saved_mib_replace;

 ZEND_DECLARE_MODULE_GLOBALS(snmp)
 static PHP_GINIT_FUNCTION(snmp);
@@ -1246,6 +1256,42 @@ static ZEND_ATTRIBUTE_NONNULL_ARGS(2) bool snmp_session_set_security(struct snmp
 }
 /* }}} */

+/* {{{ Save the snmplib state into the given php_snmp_object */
+static void save_snmplib_output_options(php_snmp_object *snmp_object)
+{
+	// Booleans
+	snmp_object->quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
+	snmp_object->enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
+	snmp_object->numeric_index = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS);
+	snmp_object->numeric_timeticks = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS);
+	snmp_object->extended_index = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX);
+	snmp_object->dont_print_units = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS);
+	snmp_object->escape_quotes = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES);
+	snmp_object->print_hex_text = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT);
+	// Integers
+	snmp_object->string_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT);
+	snmp_object->oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
+}
+/* }}} */
+
+/* {{{ Set the snmplib output options using the given php_snmp_object */
+static void set_snmplib_output_options(php_snmp_object *snmp_object)
+{
+	// Booleans
+	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, snmp_object->quick_print);
+	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, snmp_object->enum_print);
+	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS, snmp_object->numeric_index);
+	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS, snmp_object->numeric_timeticks);
+	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX, snmp_object->extended_index);
+	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS, snmp_object->dont_print_units);
+	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES, snmp_object->escape_quotes);
+	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT, snmp_object->print_hex_text);
+	// Integers
+	netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT, snmp_object->string_output_format);
+	netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, snmp_object->oid_output_format);
+}
+/* }}} */
+
 /* {{{ php_snmp
 *
 * Generic SNMP handler for all versions.
@@ -1429,12 +1475,10 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 		}
 		objid_query.oid_increasing_check = snmp_object->oid_increasing_check;
 		objid_query.valueretrieval = snmp_object->valueretrieval;
-		glob_snmp_object.enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
-		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, snmp_object->enum_print);
-		glob_snmp_object.quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
-		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, snmp_object->quick_print);
-		glob_snmp_object.oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
-		netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, snmp_object->oid_output_format);
+
+		// Save the global snmplib output options and set the options to those defined by the object instance
+		save_snmplib_output_options(&glob_snmp_object);
+		set_snmplib_output_options(snmp_object);
 	}

 	if (objid_query.max_repetitions < 0) {
@@ -1448,9 +1492,8 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 	if (session_less_mode) {
 		snmp_session_free(&session);
 	} else {
-		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, glob_snmp_object.enum_print);
-		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, glob_snmp_object.quick_print);
-		netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, glob_snmp_object.oid_output_format);
+		// Restore the snmplib output options back to the global state
+		set_snmplib_output_options(&glob_snmp_object);
 	}
 }
 /* }}} */
@@ -1527,28 +1570,147 @@ PHP_FUNCTION(snmp_set_enum_print)
 }
 /* }}} */

+/* {{{ Set walk option. */
+PHP_FUNCTION(snmp_set_mib_option)
+{
+	zend_enum_Snmp_Mib opt;
+	int snmp_opt;
+	bool val;
+
+	ZEND_PARSE_PARAMETERS_START(2, 2)
+		Z_PARAM_ENUM(opt, SnmpMib_ce)
+		Z_PARAM_BOOL(val)
+	ZEND_PARSE_PARAMETERS_END();
+
+	switch (opt) {
+		case ZEND_ENUM_Snmp_Mib_AllowUnderscores:
+			snmp_opt = NETSNMP_DS_LIB_MIB_PARSE_LABEL;
+			break;
+		case ZEND_ENUM_Snmp_Mib_CommentTerm:
+			snmp_opt = NETSNMP_DS_LIB_MIB_COMMENT_TERM;
+			break;
+		case ZEND_ENUM_Snmp_Mib_Replace:
+			snmp_opt = NETSNMP_DS_LIB_MIB_REPLACE;
+			break;
+		default:
+			ZEND_UNREACHABLE();
+	}
+	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, snmp_opt, (int) val);
+}
+/* }}} */
+
+/* {{{ Set the string output format. */
+PHP_FUNCTION(snmp_set_string_output_format)
+{
+	zend_enum_Snmp_StringOutput format;
+	int snmp_format;
+
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_ENUM(format, SnmpStringOutput_ce)
+	ZEND_PARSE_PARAMETERS_END();
+
+	switch (format) {
+		case ZEND_ENUM_Snmp_StringOutput_Guess:
+			snmp_format = NETSNMP_STRING_OUTPUT_GUESS;
+			break;
+		case ZEND_ENUM_Snmp_StringOutput_Ascii:
+			snmp_format = NETSNMP_STRING_OUTPUT_ASCII;
+			break;
+		case ZEND_ENUM_Snmp_StringOutput_Hex:
+			snmp_format = NETSNMP_STRING_OUTPUT_HEX;
+			break;
+		default:
+			ZEND_UNREACHABLE();
+	}
+	netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT, snmp_format);
+}
+/* }}} */
+
+/* {{{ Set output format option. */
+PHP_FUNCTION(snmp_set_output_option)
+{
+	zend_enum_Snmp_Output opt;
+	int snmp_opt;
+	bool val;
+
+	ZEND_PARSE_PARAMETERS_START(2, 2)
+		Z_PARAM_ENUM(opt, SnmpOutput_ce)
+		Z_PARAM_BOOL(val)
+	ZEND_PARSE_PARAMETERS_END();
+
+	switch (opt) {
+		case ZEND_ENUM_Snmp_Output_NumericIndex:
+			snmp_opt = NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS;
+			break;
+		case ZEND_ENUM_Snmp_Output_EnumPrint:
+			snmp_opt = NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM;
+			break;
+		case ZEND_ENUM_Snmp_Output_EscapeQuotes:
+			snmp_opt = NETSNMP_DS_LIB_ESCAPE_QUOTES;
+			break;
+		case ZEND_ENUM_Snmp_Output_QuickPrint:
+			snmp_opt = NETSNMP_DS_LIB_QUICK_PRINT;
+			break;
+		case ZEND_ENUM_Snmp_Output_NumericTimeticks:
+			snmp_opt = NETSNMP_DS_LIB_NUMERIC_TIMETICKS;
+			break;
+		case ZEND_ENUM_Snmp_Output_HexText:
+			snmp_opt = NETSNMP_DS_LIB_PRINT_HEX_TEXT;
+			break;
+		case ZEND_ENUM_Snmp_Output_DontPrintUnits:
+			snmp_opt = NETSNMP_DS_LIB_DONT_PRINT_UNITS;
+			break;
+		case ZEND_ENUM_Snmp_Output_ExtendedIndex:
+			snmp_opt = NETSNMP_DS_LIB_EXTENDED_INDEX;
+			break;
+		default:
+			ZEND_UNREACHABLE();
+	}
+	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, snmp_opt, (int) val);
+}
+/* }}} */
+
 /* {{{ Set the OID output format. */
 PHP_FUNCTION(snmp_set_oid_output_format)
 {
 	zend_long format;
+	int snmp_format;
+	zend_object *format_object = NULL;

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &format) == FAILURE) {
-		RETURN_THROWS();
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_OBJ_OF_CLASS_OR_LONG(format_object, SnmpOidOutput_ce, format)
+	ZEND_PARSE_PARAMETERS_END();
+
+	if (format_object != NULL) {
+		format = zend_enum_fetch_case_id(format_object);
 	}

 	switch (format) {
-		case NETSNMP_OID_OUTPUT_SUFFIX:
-		case NETSNMP_OID_OUTPUT_MODULE:
-		case NETSNMP_OID_OUTPUT_FULL:
-		case NETSNMP_OID_OUTPUT_NUMERIC:
-		case NETSNMP_OID_OUTPUT_UCD:
-		case NETSNMP_OID_OUTPUT_NONE:
-			netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, format);
-			RETURN_TRUE;
+		case ZEND_ENUM_Snmp_OidOutput_Suffix:
+			snmp_format = NETSNMP_OID_OUTPUT_SUFFIX;
+			break;
+		case ZEND_ENUM_Snmp_OidOutput_Module:
+			snmp_format = NETSNMP_OID_OUTPUT_MODULE;
+			break;
+		case ZEND_ENUM_Snmp_OidOutput_Full:
+			snmp_format = NETSNMP_OID_OUTPUT_FULL;
+			break;
+		case ZEND_ENUM_Snmp_OidOutput_Numeric:
+			snmp_format = NETSNMP_OID_OUTPUT_NUMERIC;
+			break;
+		case ZEND_ENUM_Snmp_OidOutput_Ucd:
+			snmp_format = NETSNMP_OID_OUTPUT_UCD;
+			break;
+		case ZEND_ENUM_Snmp_OidOutput_None:
+			snmp_format = NETSNMP_OID_OUTPUT_NONE;
+			break;
 		default:
-			zend_argument_value_error(1, "must be an SNMP_OID_OUTPUT_* constant");
+			zend_argument_value_error(1, "must be a Snmp\\OidOutput constant");
 			RETURN_THROWS();
 	}
+
+	netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, snmp_format);
+	RETURN_TRUE;
 }
 /* }}} */

@@ -1731,9 +1893,7 @@ PHP_METHOD(SNMP, __construct)
 	}
 	snmp_object->max_oids = 0;
 	snmp_object->valueretrieval = SNMP_G(valueretrieval);
-	snmp_object->enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
-	snmp_object->oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
-	snmp_object->quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
+	save_snmplib_output_options(snmp_object);
 	snmp_object->oid_increasing_check = true;
 	snmp_object->exceptions_enabled = 0;
 }
@@ -1812,6 +1972,74 @@ PHP_METHOD(SNMP, setSecurity)
 }
 /* }}} */

+/* {{{ Set OID output format */
+PHP_METHOD(SNMP, setOidOutputFormat)
+{
+	php_snmp_object *snmp_object;
+	zval *object = ZEND_THIS;
+	zend_enum_Snmp_OidOutput format;
+
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_ENUM(format, SnmpOidOutput_ce)
+	ZEND_PARSE_PARAMETERS_END();
+
+	snmp_object = Z_SNMP_P(object);
+
+	switch (format) {
+		case ZEND_ENUM_Snmp_OidOutput_Suffix:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_SUFFIX;
+			RETURN_TRUE;
+		case ZEND_ENUM_Snmp_OidOutput_Module:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_MODULE;
+			RETURN_TRUE;
+		case ZEND_ENUM_Snmp_OidOutput_Full:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_FULL;
+			RETURN_TRUE;
+		case ZEND_ENUM_Snmp_OidOutput_Numeric:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_NUMERIC;
+			RETURN_TRUE;
+		case ZEND_ENUM_Snmp_OidOutput_Ucd:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_UCD;
+			RETURN_TRUE;
+		case ZEND_ENUM_Snmp_OidOutput_None:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_NONE;
+			RETURN_TRUE;
+		default:
+			ZEND_UNREACHABLE();
+	}
+
+}
+/* }}} */
+
+/* {{{ Set string output format */
+PHP_METHOD(SNMP, setStringOutputFormat)
+{
+	php_snmp_object *snmp_object;
+	zval *object = ZEND_THIS;
+	zend_enum_Snmp_StringOutput format;
+
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_ENUM(format, SnmpStringOutput_ce)
+	ZEND_PARSE_PARAMETERS_END();
+
+	snmp_object = Z_SNMP_P(object);
+
+	switch (format) {
+		case ZEND_ENUM_Snmp_StringOutput_Guess:
+			snmp_object->string_output_format = NETSNMP_STRING_OUTPUT_GUESS;
+			RETURN_TRUE;
+		case ZEND_ENUM_Snmp_StringOutput_Ascii:
+			snmp_object->string_output_format = NETSNMP_STRING_OUTPUT_ASCII;
+			RETURN_TRUE;
+		case ZEND_ENUM_Snmp_StringOutput_Hex:
+			snmp_object->string_output_format = NETSNMP_STRING_OUTPUT_HEX;
+			RETURN_TRUE;
+		default:
+			ZEND_UNREACHABLE();
+	}
+}
+/* }}} */
+
 /* {{{ Get last error code number */
 PHP_METHOD(SNMP, getErrno)
 {
@@ -2033,6 +2261,35 @@ static zend_result php_snmp_read_max_oids(php_snmp_object *snmp_object, zval *re
 }
 /* }}} */

+/* {{{ */
+static zend_result php_snmp_read_oid_output_format(php_snmp_object *snmp_object, zval *retval)
+{
+	switch(snmp_object->oid_output_format) {
+		case NETSNMP_OID_OUTPUT_SUFFIX:
+			ZVAL_LONG(retval, ZEND_ENUM_Snmp_OidOutput_Suffix);
+			return SUCCESS;
+		case NETSNMP_OID_OUTPUT_MODULE:
+			ZVAL_LONG(retval, ZEND_ENUM_Snmp_OidOutput_Module);
+			return SUCCESS;
+		case NETSNMP_OID_OUTPUT_FULL:
+			ZVAL_LONG(retval, ZEND_ENUM_Snmp_OidOutput_Full);
+			return SUCCESS;
+		case NETSNMP_OID_OUTPUT_NUMERIC:
+			ZVAL_LONG(retval, ZEND_ENUM_Snmp_OidOutput_Numeric);
+			return SUCCESS;
+		case NETSNMP_OID_OUTPUT_UCD:
+			ZVAL_LONG(retval, ZEND_ENUM_Snmp_OidOutput_Ucd);
+			return SUCCESS;
+		case NETSNMP_OID_OUTPUT_NONE:
+			ZVAL_LONG(retval, ZEND_ENUM_Snmp_OidOutput_None);
+			return SUCCESS;
+		default:
+			ZVAL_NULL(retval);
+			return SUCCESS;
+	}
+}
+/* }}} */
+
 #define PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(name) \
 	static zend_result php_snmp_read_##name(php_snmp_object *snmp_object, zval *retval) \
 	{ \
@@ -2043,6 +2300,12 @@ static zend_result php_snmp_read_max_oids(php_snmp_object *snmp_object, zval *re
 PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(oid_increasing_check)
 PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(quick_print)
 PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(enum_print)
+PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(numeric_index)
+PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(numeric_timeticks)
+PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(extended_index)
+PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(dont_print_units)
+PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(escape_quotes)
+PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(print_hex_text)

 #define PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(name) \
 	static zend_result php_snmp_read_##name(php_snmp_object *snmp_object, zval *retval) \
@@ -2052,7 +2315,6 @@ PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(enum_print)
 	}

 PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(valueretrieval)
-PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(oid_output_format)
 PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(exceptions_enabled)

 /* {{{ */
@@ -2106,9 +2368,15 @@ static zend_result php_snmp_write_##name(php_snmp_object *snmp_object, zval *new
 	return SUCCESS; \
 }

+PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(oid_increasing_check)
 PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(quick_print)
 PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(enum_print)
-PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(oid_increasing_check)
+PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(numeric_index)
+PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(numeric_timeticks)
+PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(extended_index)
+PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(dont_print_units)
+PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(escape_quotes)
+PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(print_hex_text)

 /* {{{ */
 static zend_result php_snmp_write_oid_output_format(php_snmp_object *snmp_object, zval *newval)
@@ -2116,16 +2384,26 @@ static zend_result php_snmp_write_oid_output_format(php_snmp_object *snmp_object
 	zend_long lval = zval_get_long(newval);

 	switch(lval) {
-		case NETSNMP_OID_OUTPUT_SUFFIX:
-		case NETSNMP_OID_OUTPUT_MODULE:
-		case NETSNMP_OID_OUTPUT_FULL:
-		case NETSNMP_OID_OUTPUT_NUMERIC:
-		case NETSNMP_OID_OUTPUT_UCD:
-		case NETSNMP_OID_OUTPUT_NONE:
-			snmp_object->oid_output_format = lval;
+		case ZEND_ENUM_Snmp_OidOutput_Suffix:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_SUFFIX;
+			return SUCCESS;
+		case ZEND_ENUM_Snmp_OidOutput_Module:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_MODULE;
+			return SUCCESS;
+		case ZEND_ENUM_Snmp_OidOutput_Full:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_FULL;
+			return SUCCESS;
+		case ZEND_ENUM_Snmp_OidOutput_Numeric:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_NUMERIC;
+			return SUCCESS;
+		case ZEND_ENUM_Snmp_OidOutput_Ucd:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_UCD;
+			return SUCCESS;
+		case ZEND_ENUM_Snmp_OidOutput_None:
+			snmp_object->oid_output_format = NETSNMP_OID_OUTPUT_NONE;
 			return SUCCESS;
 		default:
-			zend_value_error("SNMP output print format must be an SNMP_OID_OUTPUT_* constant");
+			zend_value_error("SNMP output print format must be a SNMP_OID_OUTPUT_* constant");
 			return FAILURE;
 	}
 }
@@ -2155,11 +2433,17 @@ static void free_php_snmp_properties(zval *el)  /* {{{ */
 const php_snmp_prop_handler php_snmp_property_entries[] = {
 	PHP_SNMP_READONLY_PROPERTY_ENTRY_RECORD(info),
 	PHP_SNMP_PROPERTY_ENTRY_RECORD(max_oids),
-	PHP_SNMP_PROPERTY_ENTRY_RECORD(valueretrieval),
+	PHP_SNMP_PROPERTY_ENTRY_RECORD(oid_increasing_check),
 	PHP_SNMP_PROPERTY_ENTRY_RECORD(quick_print),
 	PHP_SNMP_PROPERTY_ENTRY_RECORD(enum_print),
+	PHP_SNMP_PROPERTY_ENTRY_RECORD(numeric_index),
+	PHP_SNMP_PROPERTY_ENTRY_RECORD(numeric_timeticks),
+	PHP_SNMP_PROPERTY_ENTRY_RECORD(extended_index),
+	PHP_SNMP_PROPERTY_ENTRY_RECORD(dont_print_units),
+	PHP_SNMP_PROPERTY_ENTRY_RECORD(escape_quotes),
+	PHP_SNMP_PROPERTY_ENTRY_RECORD(print_hex_text),
+	PHP_SNMP_PROPERTY_ENTRY_RECORD(valueretrieval),
 	PHP_SNMP_PROPERTY_ENTRY_RECORD(oid_output_format),
-	PHP_SNMP_PROPERTY_ENTRY_RECORD(oid_increasing_check),
 	PHP_SNMP_PROPERTY_ENTRY_RECORD(exceptions_enabled),
 	{ NULL, 0, NULL, NULL}
 };
@@ -2209,6 +2493,12 @@ PHP_MINIT_FUNCTION(snmp)
 	/* Register SNMPException class */
 	php_snmp_exception_ce = register_class_SNMPException(spl_ce_RuntimeException);

+	/* Register enums */
+	SnmpMib_ce = register_class_Snmp_Mib();
+	SnmpOidOutput_ce = register_class_Snmp_OidOutput();
+	SnmpOutput_ce = register_class_Snmp_Output();
+	SnmpStringOutput_ce = register_class_Snmp_StringOutput();
+
 	register_snmp_symbols(module_number);

 	return SUCCESS;
@@ -2226,6 +2516,21 @@ PHP_MSHUTDOWN_FUNCTION(snmp)
 }
 /* }}} */

+/* {{{ PHP_INIT_FUNCTION */
+static PHP_RINIT_FUNCTION(snmp)
+{
+	// Save the output options
+	save_snmplib_output_options(&saved_snmp_settings);
+
+	// Save the MIB options
+	saved_mib_allow_underscores = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_PARSE_LABEL);
+	saved_mib_comment_term = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_COMMENT_TERM);
+	saved_mib_replace = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_REPLACE);
+
+	return SUCCESS;
+}
+/* }}} */
+
 /* {{{ PHP_RSHUTDOWN_FUNCTION */
 static PHP_RSHUTDOWN_FUNCTION(snmp)
 {
@@ -2239,6 +2544,14 @@ static PHP_RSHUTDOWN_FUNCTION(snmp)
 #endif
 	}

+	// Restore the output options
+	set_snmplib_output_options(&saved_snmp_settings);
+
+	// Restore MIB options
+	netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_PARSE_LABEL, saved_mib_allow_underscores);
+	netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_COMMENT_TERM, saved_mib_comment_term);
+	netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_REPLACE, saved_mib_replace);
+
 	return SUCCESS;
 }
 /* }}} */
@@ -2269,7 +2582,7 @@ zend_module_entry snmp_module_entry = {
 	ext_functions,
 	PHP_MINIT(snmp),
 	PHP_MSHUTDOWN(snmp),
-	NULL,
+	PHP_RINIT(snmp),
 	PHP_RSHUTDOWN(snmp),
 	PHP_MINFO(snmp),
 	PHP_SNMP_VERSION,
diff --git a/ext/snmp/snmp.stub.php b/ext/snmp/snmp.stub.php
index b40a2fcd9f2..f68da7e75f1 100644
--- a/ext/snmp/snmp.stub.php
+++ b/ext/snmp/snmp.stub.php
@@ -1,36 +1,40 @@
 <?php

-/** @generate-class-entries */
+/**
+ * @generate-class-entries
+ * @generate-c-enums
+ */
+
 namespace
 {
     /**
      * @var int
-     * @cvalue NETSNMP_OID_OUTPUT_SUFFIX
+     * @cvalue ZEND_ENUM_Snmp_OidOutput_Suffix
      */
     const SNMP_OID_OUTPUT_SUFFIX = UNKNOWN;
     /**
      * @var int
-     * @cvalue NETSNMP_OID_OUTPUT_MODULE
+     * @cvalue ZEND_ENUM_Snmp_OidOutput_Module
      */
     const SNMP_OID_OUTPUT_MODULE = UNKNOWN;
     /**
      * @var int
-     * @cvalue NETSNMP_OID_OUTPUT_FULL
+     * @cvalue ZEND_ENUM_Snmp_OidOutput_Full
      */
     const SNMP_OID_OUTPUT_FULL = UNKNOWN;
     /**
      * @var int
-     * @cvalue NETSNMP_OID_OUTPUT_NUMERIC
+     * @cvalue ZEND_ENUM_Snmp_OidOutput_Numeric
      */
     const SNMP_OID_OUTPUT_NUMERIC = UNKNOWN;
     /**
      * @var int
-     * @cvalue NETSNMP_OID_OUTPUT_UCD
+     * @cvalue ZEND_ENUM_Snmp_OidOutput_Ucd
      */
     const SNMP_OID_OUTPUT_UCD = UNKNOWN;
     /**
      * @var int
-     * @cvalue NETSNMP_OID_OUTPUT_NONE
+     * @cvalue ZEND_ENUM_Snmp_OidOutput_None
      */
     const SNMP_OID_OUTPUT_NONE = UNKNOWN;

@@ -130,10 +134,16 @@ function snmp_set_quick_print(bool $enable): true {}

     function snmp_set_enum_print(bool $enable): true {}

-    function snmp_set_oid_output_format(int $format): true {}
+    function snmp_set_mib_option(Snmp\Mib $option, bool $enable): void {}
+
+    function snmp_set_oid_output_format(Snmp\OidOutput|int $format): true {}
+
+    function snmp_set_output_option(Snmp\Output $option, bool $enable): void {}
+
+    function snmp_set_string_output_format(Snmp\StringOutput $format): void {}

     /** @alias snmp_set_oid_output_format */
-    function snmp_set_oid_numeric_print(int $format): true {}
+    function snmp_set_oid_numeric_print(Snmp\OidOutput|int $format): true {}

     function snmp2_get(string $hostname, string $community, array|string $object_id, int $timeout = -1, int $retries = -1): mixed {}

@@ -216,11 +226,17 @@ class SNMP
         /** @readonly */
         public array $info;
         public ?int $max_oids;
-        public int $valueretrieval;
+        public bool $oid_increasing_check;
         public bool $quick_print;
         public bool $enum_print;
+        public bool $numeric_index;
+        public bool $numeric_timeticks;
+        public bool $extended_index;
+        public bool $dont_print_units;
+        public bool $escape_quotes;
+        public bool $print_hex_text;
+        public int $valueretrieval;
         public int $oid_output_format;
-        public bool $oid_increasing_check;
         public int $exceptions_enabled;

         public function __construct(int $version, string $hostname, string $community, int $timeout = -1, int $retries = -1) {}
@@ -234,6 +250,12 @@ public function setSecurity(
             string $privacyProtocol = "", string $privacyPassphrase = "",
             string $contextName = "", string $contextEngineId = ""): bool {}

+	    /** @tentative-return-type */
+	    public function setOidOutputFormat (Snmp\OidOutput $format): bool {}
+
+	    /** @tentative-return-type */
+	    public function setStringOutputFormat (Snmp\StringOutput $format): bool {}
+
         /** @tentative-return-type */
         public function get(array|string $objectId, bool $preserveKeys = false): mixed {}

@@ -257,3 +279,41 @@ class SNMPException extends RuntimeException
     {
     }
 }
+
+namespace Snmp {
+    enum Mib
+    {
+        case AllowUnderscores;
+        case CommentTerm;
+        case Replace;
+    }
+
+    enum OidOutput
+    {
+        case Suffix;
+        case Module;
+        case Full;
+        case Numeric;
+        case Ucd;
+        case None;
+    }
+
+    enum Output
+    {
+        case NumericIndex;
+        case EnumPrint;
+        case EscapeQuotes;
+        case QuickPrint;
+        case NumericTimeticks;
+        case HexText;
+        case DontPrintUnits;
+        case ExtendedIndex;
+    }
+
+    enum StringOutput
+    {
+        case Guess;
+        case Ascii;
+        case Hex;
+    }
+}
diff --git a/ext/snmp/snmp_arginfo.h b/ext/snmp/snmp_arginfo.h
index d2faf5056b5..67d72cf75bd 100644
Binary files a/ext/snmp/snmp_arginfo.h and b/ext/snmp/snmp_arginfo.h differ
diff --git a/ext/snmp/snmp_decl.h b/ext/snmp/snmp_decl.h
new file mode 100644
index 00000000000..78fad4608a2
Binary files /dev/null and b/ext/snmp/snmp_decl.h differ
diff --git a/ext/snmp/tests/snmp-object-properties.phpt b/ext/snmp/tests/snmp-object-properties.phpt
index a8fccd406b7..76060aaba48 100644
--- a/ext/snmp/tests/snmp-object-properties.phpt
+++ b/ext/snmp/tests/snmp-object-properties.phpt
@@ -92,16 +92,28 @@
   }
   ["max_oids"]=>
   NULL
-  ["valueretrieval"]=>
-  int(1)
+  ["oid_increasing_check"]=>
+  bool(true)
   ["quick_print"]=>
   bool(false)
   ["enum_print"]=>
   bool(false)
+  ["numeric_index"]=>
+  bool(false)
+  ["numeric_timeticks"]=>
+  bool(false)
+  ["extended_index"]=>
+  bool(false)
+  ["dont_print_units"]=>
+  bool(false)
+  ["escape_quotes"]=>
+  bool(false)
+  ["print_hex_text"]=>
+  bool(false)
+  ["valueretrieval"]=>
+  int(1)
   ["oid_output_format"]=>
   int(3)
-  ["oid_increasing_check"]=>
-  bool(true)
   ["exceptions_enabled"]=>
   int(0)
 }
@@ -117,16 +129,28 @@
   }
   ["max_oids"]=>
   int(40)
-  ["valueretrieval"]=>
-  int(0)
+  ["oid_increasing_check"]=>
+  bool(false)
   ["quick_print"]=>
   bool(true)
   ["enum_print"]=>
   bool(true)
+  ["numeric_index"]=>
+  bool(false)
+  ["numeric_timeticks"]=>
+  bool(false)
+  ["extended_index"]=>
+  bool(false)
+  ["dont_print_units"]=>
+  bool(false)
+  ["escape_quotes"]=>
+  bool(false)
+  ["print_hex_text"]=>
+  bool(false)
+  ["valueretrieval"]=>
+  int(0)
   ["oid_output_format"]=>
   int(4)
-  ["oid_increasing_check"]=>
-  bool(false)
   ["exceptions_enabled"]=>
   int(0)
 }
@@ -142,16 +166,28 @@
   }
   ["max_oids"]=>
   int(40)
-  ["valueretrieval"]=>
-  int(1)
+  ["oid_increasing_check"]=>
+  bool(true)
   ["quick_print"]=>
   bool(true)
   ["enum_print"]=>
   bool(true)
+  ["numeric_index"]=>
+  bool(false)
+  ["numeric_timeticks"]=>
+  bool(false)
+  ["extended_index"]=>
+  bool(false)
+  ["dont_print_units"]=>
+  bool(false)
+  ["escape_quotes"]=>
+  bool(false)
+  ["print_hex_text"]=>
+  bool(false)
+  ["valueretrieval"]=>
+  int(1)
   ["oid_output_format"]=>
   int(3)
-  ["oid_increasing_check"]=>
-  bool(true)
   ["exceptions_enabled"]=>
   int(0)
 }
@@ -172,16 +208,28 @@
   }
   ["max_oids"]=>
   int(40)
-  ["valueretrieval"]=>
-  int(1)
+  ["oid_increasing_check"]=>
+  bool(true)
   ["quick_print"]=>
   bool(true)
   ["enum_print"]=>
   bool(true)
+  ["numeric_index"]=>
+  bool(false)
+  ["numeric_timeticks"]=>
+  bool(false)
+  ["extended_index"]=>
+  bool(false)
+  ["dont_print_units"]=>
+  bool(false)
+  ["escape_quotes"]=>
+  bool(false)
+  ["print_hex_text"]=>
+  bool(false)
+  ["valueretrieval"]=>
+  int(1)
   ["oid_output_format"]=>
   int(3)
-  ["oid_increasing_check"]=>
-  bool(true)
   ["exceptions_enabled"]=>
   int(0)
   ["123"]=>
@@ -195,6 +243,6 @@
 NULL
 bool(false)
 SNMP retrieval method must be a bitmask of SNMP_VALUE_LIBRARY, SNMP_VALUE_PLAIN, and SNMP_VALUE_OBJECT
-SNMP output print format must be an SNMP_OID_OUTPUT_* constant
+SNMP output print format must be a SNMP_OID_OUTPUT_* constant
 Cannot write read-only property SNMP::$info
 NULL
diff --git a/ext/snmp/tests/snmp_set_oid_output_format.phpt b/ext/snmp/tests/snmp_set_oid_output_format.phpt
index bb8c63bdda1..582ba79e7c2 100644
--- a/ext/snmp/tests/snmp_set_oid_output_format.phpt
+++ b/ext/snmp/tests/snmp_set_oid_output_format.phpt
@@ -26,7 +26,7 @@
 ?>
 --EXPECT--
 Checking error handling
-snmp_set_oid_output_format(): Argument #1 ($format) must be an SNMP_OID_OUTPUT_* constant
+snmp_set_oid_output_format(): Argument #1 ($format) must be a Snmp\OidOutput constant
 Checking working
 bool(true)
 bool(true)