File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / snmp / snmp.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:34:42 2012 UTC (12 years, 2 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_17p0, HEAD
php 5.4.3+patches

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2012 The PHP Group                                |
    6:    +----------------------------------------------------------------------+
    7:    | This source file is subject to version 3.01 of the PHP license,      |
    8:    | that is bundled with this package in the file LICENSE, and is        |
    9:    | available through the world-wide-web at the following url:           |
   10:    | http://www.php.net/license/3_01.txt                                  |
   11:    | If you did not receive a copy of the PHP license and are unable to   |
   12:    | obtain it through the world-wide-web, please send a note to          |
   13:    | license@php.net so we can mail you a copy immediately.               |
   14:    +----------------------------------------------------------------------+
   15:    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
   16:    |          Mike Jackson <mhjack@tscnet.com>                            |
   17:    |          Steven Lawrance <slawrance@technologist.com>                |
   18:    |          Harrie Hazewinkel <harrie@lisanza.net>                      |
   19:    |          Johann Hanne <jonny@nurfuerspam.de>                         |
   20:    |          Boris Lytockin <lytboris@gmail.com>                         |
   21:    +----------------------------------------------------------------------+
   22:  */
   23: 
   24: /* $Id: snmp.c,v 1.1.1.2 2012/05/29 12:34:42 misho Exp $ */
   25: 
   26: #ifdef HAVE_CONFIG_H
   27: #include "config.h"
   28: #endif
   29: 
   30: #include "php.h"
   31: #include "main/php_network.h"
   32: #include "ext/standard/info.h"
   33: #include "php_snmp.h"
   34: 
   35: #include "zend_exceptions.h"
   36: 
   37: #if HAVE_SPL
   38: #include "ext/spl/spl_exceptions.h"
   39: #endif
   40: 
   41: #if HAVE_SNMP
   42: 
   43: #include <sys/types.h>
   44: #ifdef PHP_WIN32
   45: #include <winsock2.h>
   46: #include <errno.h>
   47: #include <process.h>
   48: #include "win32/time.h"
   49: #elif defined(NETWARE)
   50: #ifdef USE_WINSOCK
   51: #include <novsock2.h>
   52: #else
   53: #include <sys/socket.h>
   54: #endif
   55: #include <errno.h>
   56: #include <sys/timeval.h>
   57: #else
   58: #include <sys/socket.h>
   59: #include <netinet/in.h>
   60: #include <arpa/inet.h>
   61: #ifndef _OSD_POSIX
   62: #include <sys/errno.h>
   63: #else
   64: #include <errno.h>  /* BS2000/OSD uses <errno.h>, not <sys/errno.h> */
   65: #endif
   66: #include <netdb.h>
   67: #endif
   68: #ifdef HAVE_UNISTD_H
   69: #include <unistd.h>
   70: #endif
   71: 
   72: #ifndef __P
   73: #ifdef __GNUC__
   74: #define __P(args) args
   75: #else
   76: #define __P(args) ()
   77: #endif
   78: #endif
   79: 
   80: #include <net-snmp/net-snmp-config.h>
   81: #include <net-snmp/net-snmp-includes.h>
   82: 
   83: /* For net-snmp prior to 5.4 */
   84: #ifndef HAVE_SHUTDOWN_SNMP_LOGGING
   85: extern netsnmp_log_handler *logh_head;
   86: #define shutdown_snmp_logging() \
   87: 	{ \
   88: 		snmp_disable_log(); \
   89: 		while(NULL != logh_head) \
   90: 			netsnmp_remove_loghandler( logh_head ); \
   91: 	}
   92: #endif
   93: 
   94: #define SNMP_VALUE_LIBRARY	(0 << 0)
   95: #define SNMP_VALUE_PLAIN	(1 << 0)
   96: #define SNMP_VALUE_OBJECT	(1 << 1)
   97: 
   98: typedef struct snmp_session php_snmp_session;
   99: #define PHP_SNMP_SESSION_RES_NAME "SNMP session"
  100: 
  101: #define PHP_SNMP_ADD_PROPERTIES(a, b) \
  102: { \
  103: 	int i = 0; \
  104: 	while (b[i].name != NULL) { \
  105: 		php_snmp_add_property((a), (b)[i].name, (b)[i].name_length, \
  106: 							(php_snmp_read_t)(b)[i].read_func, (php_snmp_write_t)(b)[i].write_func TSRMLS_CC); \
  107: 		i++; \
  108: 	} \
  109: }
  110: 
  111: #define PHP_SNMP_ERRNO_NOERROR			0
  112: #define PHP_SNMP_ERRNO_GENERIC			(1 << 1)
  113: #define PHP_SNMP_ERRNO_TIMEOUT			(1 << 2)
  114: #define PHP_SNMP_ERRNO_ERROR_IN_REPLY		(1 << 3)
  115: #define PHP_SNMP_ERRNO_OID_NOT_INCREASING	(1 << 4)
  116: #define PHP_SNMP_ERRNO_OID_PARSING_ERROR	(1 << 5)
  117: #define PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES	(1 << 6)
  118: #define PHP_SNMP_ERRNO_ANY	( \
  119: 		PHP_SNMP_ERRNO_GENERIC | \
  120: 		PHP_SNMP_ERRNO_TIMEOUT | \
  121: 		PHP_SNMP_ERRNO_ERROR_IN_REPLY | \
  122: 		PHP_SNMP_ERRNO_OID_NOT_INCREASING | \
  123: 		PHP_SNMP_ERRNO_OID_PARSING_ERROR | \
  124: 		PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES | \
  125: 		PHP_SNMP_ERRNO_NOERROR \
  126: 	)
  127: 
  128: ZEND_DECLARE_MODULE_GLOBALS(snmp)
  129: static PHP_GINIT_FUNCTION(snmp);
  130: 
  131: /* constant - can be shared among threads */
  132: static oid objid_mib[] = {1, 3, 6, 1, 2, 1};
  133: 
  134: static int le_snmp_session;
  135: 
  136: /* Handlers */
  137: static zend_object_handlers php_snmp_object_handlers;
  138: 
  139: /* Class entries */
  140: zend_class_entry *php_snmp_ce;
  141: zend_class_entry *php_snmp_exception_ce;
  142: 
  143: /* Class object properties */
  144: static HashTable php_snmp_properties;
  145: 
  146: /* {{{ arginfo */
  147: 
  148: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpget, 0, 0, 3)
  149: 	ZEND_ARG_INFO(0, host)
  150: 	ZEND_ARG_INFO(0, community)
  151: 	ZEND_ARG_INFO(0, object_id)
  152: 	ZEND_ARG_INFO(0, timeout)
  153: 	ZEND_ARG_INFO(0, retries)
  154: ZEND_END_ARG_INFO()
  155: 
  156: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpgetnext, 0, 0, 3)
  157: 	ZEND_ARG_INFO(0, host)
  158: 	ZEND_ARG_INFO(0, community)
  159: 	ZEND_ARG_INFO(0, object_id)
  160: 	ZEND_ARG_INFO(0, timeout)
  161: 	ZEND_ARG_INFO(0, retries)
  162: ZEND_END_ARG_INFO()
  163: 
  164: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpwalk, 0, 0, 3)
  165: 	ZEND_ARG_INFO(0, host)
  166: 	ZEND_ARG_INFO(0, community)
  167: 	ZEND_ARG_INFO(0, object_id)
  168: 	ZEND_ARG_INFO(0, timeout)
  169: 	ZEND_ARG_INFO(0, retries)
  170: ZEND_END_ARG_INFO()
  171: 
  172: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmprealwalk, 0, 0, 3)
  173: 	ZEND_ARG_INFO(0, host)
  174: 	ZEND_ARG_INFO(0, community)
  175: 	ZEND_ARG_INFO(0, object_id)
  176: 	ZEND_ARG_INFO(0, timeout)
  177: 	ZEND_ARG_INFO(0, retries)
  178: ZEND_END_ARG_INFO()
  179: 
  180: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpset, 0, 0, 5)
  181: 	ZEND_ARG_INFO(0, host)
  182: 	ZEND_ARG_INFO(0, community)
  183: 	ZEND_ARG_INFO(0, object_id)
  184: 	ZEND_ARG_INFO(0, type)
  185: 	ZEND_ARG_INFO(0, value)
  186: 	ZEND_ARG_INFO(0, timeout)
  187: 	ZEND_ARG_INFO(0, retries)
  188: ZEND_END_ARG_INFO()
  189: 
  190: 
  191: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_get_quick_print, 0, 0, 1)
  192: 	ZEND_ARG_INFO(0, d)
  193: ZEND_END_ARG_INFO()
  194: 
  195: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_quick_print, 0, 0, 1)
  196: 	ZEND_ARG_INFO(0, quick_print)
  197: ZEND_END_ARG_INFO()
  198: 
  199: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_enum_print, 0, 0, 1)
  200: 	ZEND_ARG_INFO(0, enum_print)
  201: ZEND_END_ARG_INFO()
  202: 
  203: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_oid_output_format, 0, 0, 1)
  204: 	ZEND_ARG_INFO(0, oid_format)
  205: ZEND_END_ARG_INFO()
  206: 
  207: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_get, 0, 0, 3)
  208: 	ZEND_ARG_INFO(0, host)
  209: 	ZEND_ARG_INFO(0, community)
  210: 	ZEND_ARG_INFO(0, object_id)
  211: 	ZEND_ARG_INFO(0, timeout)
  212: 	ZEND_ARG_INFO(0, retries)
  213: ZEND_END_ARG_INFO()
  214: 
  215: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_getnext, 0, 0, 3)
  216: 	ZEND_ARG_INFO(0, host)
  217: 	ZEND_ARG_INFO(0, community)
  218: 	ZEND_ARG_INFO(0, object_id)
  219: 	ZEND_ARG_INFO(0, timeout)
  220: 	ZEND_ARG_INFO(0, retries)
  221: ZEND_END_ARG_INFO()
  222: 
  223: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_walk, 0, 0, 3)
  224: 	ZEND_ARG_INFO(0, host)
  225: 	ZEND_ARG_INFO(0, community)
  226: 	ZEND_ARG_INFO(0, object_id)
  227: 	ZEND_ARG_INFO(0, timeout)
  228: 	ZEND_ARG_INFO(0, retries)
  229: ZEND_END_ARG_INFO()
  230: 
  231: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_real_walk, 0, 0, 3)
  232: 	ZEND_ARG_INFO(0, host)
  233: 	ZEND_ARG_INFO(0, community)
  234: 	ZEND_ARG_INFO(0, object_id)
  235: 	ZEND_ARG_INFO(0, timeout)
  236: 	ZEND_ARG_INFO(0, retries)
  237: ZEND_END_ARG_INFO()
  238: 
  239: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_set, 0, 0, 5)
  240: 	ZEND_ARG_INFO(0, host)
  241: 	ZEND_ARG_INFO(0, community)
  242: 	ZEND_ARG_INFO(0, object_id)
  243: 	ZEND_ARG_INFO(0, type)
  244: 	ZEND_ARG_INFO(0, value)
  245: 	ZEND_ARG_INFO(0, timeout)
  246: 	ZEND_ARG_INFO(0, retries)
  247: ZEND_END_ARG_INFO()
  248: 
  249: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_get, 0, 0, 8)
  250: 	ZEND_ARG_INFO(0, host)
  251: 	ZEND_ARG_INFO(0, sec_name)
  252: 	ZEND_ARG_INFO(0, sec_level)
  253: 	ZEND_ARG_INFO(0, auth_protocol)
  254: 	ZEND_ARG_INFO(0, auth_passphrase)
  255: 	ZEND_ARG_INFO(0, priv_protocol)
  256: 	ZEND_ARG_INFO(0, priv_passphrase)
  257: 	ZEND_ARG_INFO(0, object_id)
  258: 	ZEND_ARG_INFO(0, timeout)
  259: 	ZEND_ARG_INFO(0, retries)
  260: ZEND_END_ARG_INFO()
  261: 
  262: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_getnext, 0, 0, 8)
  263: 	ZEND_ARG_INFO(0, host)
  264: 	ZEND_ARG_INFO(0, sec_name)
  265: 	ZEND_ARG_INFO(0, sec_level)
  266: 	ZEND_ARG_INFO(0, auth_protocol)
  267: 	ZEND_ARG_INFO(0, auth_passphrase)
  268: 	ZEND_ARG_INFO(0, priv_protocol)
  269: 	ZEND_ARG_INFO(0, priv_passphrase)
  270: 	ZEND_ARG_INFO(0, object_id)
  271: 	ZEND_ARG_INFO(0, timeout)
  272: 	ZEND_ARG_INFO(0, retries)
  273: ZEND_END_ARG_INFO()
  274: 
  275: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_walk, 0, 0, 8)
  276: 	ZEND_ARG_INFO(0, host)
  277: 	ZEND_ARG_INFO(0, sec_name)
  278: 	ZEND_ARG_INFO(0, sec_level)
  279: 	ZEND_ARG_INFO(0, auth_protocol)
  280: 	ZEND_ARG_INFO(0, auth_passphrase)
  281: 	ZEND_ARG_INFO(0, priv_protocol)
  282: 	ZEND_ARG_INFO(0, priv_passphrase)
  283: 	ZEND_ARG_INFO(0, object_id)
  284: 	ZEND_ARG_INFO(0, timeout)
  285: 	ZEND_ARG_INFO(0, retries)
  286: ZEND_END_ARG_INFO()
  287: 
  288: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_real_walk, 0, 0, 8)
  289: 	ZEND_ARG_INFO(0, host)
  290: 	ZEND_ARG_INFO(0, sec_name)
  291: 	ZEND_ARG_INFO(0, sec_level)
  292: 	ZEND_ARG_INFO(0, auth_protocol)
  293: 	ZEND_ARG_INFO(0, auth_passphrase)
  294: 	ZEND_ARG_INFO(0, priv_protocol)
  295: 	ZEND_ARG_INFO(0, priv_passphrase)
  296: 	ZEND_ARG_INFO(0, object_id)
  297: 	ZEND_ARG_INFO(0, timeout)
  298: 	ZEND_ARG_INFO(0, retries)
  299: ZEND_END_ARG_INFO()
  300: 
  301: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_set, 0, 0, 10)
  302: 	ZEND_ARG_INFO(0, host)
  303: 	ZEND_ARG_INFO(0, sec_name)
  304: 	ZEND_ARG_INFO(0, sec_level)
  305: 	ZEND_ARG_INFO(0, auth_protocol)
  306: 	ZEND_ARG_INFO(0, auth_passphrase)
  307: 	ZEND_ARG_INFO(0, priv_protocol)
  308: 	ZEND_ARG_INFO(0, priv_passphrase)
  309: 	ZEND_ARG_INFO(0, object_id)
  310: 	ZEND_ARG_INFO(0, type)
  311: 	ZEND_ARG_INFO(0, value)
  312: 	ZEND_ARG_INFO(0, timeout)
  313: 	ZEND_ARG_INFO(0, retries)
  314: ZEND_END_ARG_INFO()
  315: 
  316: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_valueretrieval, 0, 0, 1)
  317: 	ZEND_ARG_INFO(0, method)
  318: ZEND_END_ARG_INFO()
  319: 
  320: ZEND_BEGIN_ARG_INFO(arginfo_snmp_get_valueretrieval, 0)
  321: ZEND_END_ARG_INFO()
  322: 
  323: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_read_mib, 0, 0, 1)
  324: 	ZEND_ARG_INFO(0, filename)
  325: ZEND_END_ARG_INFO()
  326: 
  327: /* OO arginfo */
  328: 
  329: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_create, 0, 0, 3)
  330: 	ZEND_ARG_INFO(0, version)
  331: 	ZEND_ARG_INFO(0, host)
  332: 	ZEND_ARG_INFO(0, community)
  333: 	ZEND_ARG_INFO(0, timeout)
  334: 	ZEND_ARG_INFO(0, retries)
  335: ZEND_END_ARG_INFO()
  336: 
  337: ZEND_BEGIN_ARG_INFO(arginfo_snmp_void, 0)
  338: ZEND_END_ARG_INFO()
  339: 
  340: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_setSecurity, 0, 0, 8)
  341: 	ZEND_ARG_INFO(0, session)
  342: 	ZEND_ARG_INFO(0, sec_level)
  343: 	ZEND_ARG_INFO(0, auth_protocol)
  344: 	ZEND_ARG_INFO(0, auth_passphrase)
  345: 	ZEND_ARG_INFO(0, priv_protocol)
  346: 	ZEND_ARG_INFO(0, priv_passphrase)
  347: 	ZEND_ARG_INFO(0, contextName)
  348: 	ZEND_ARG_INFO(0, contextEngineID)
  349: 	ZEND_ARG_INFO(0, )
  350: ZEND_END_ARG_INFO()
  351: 
  352: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_get, 0, 0, 1)
  353: 	ZEND_ARG_INFO(0, object_id)
  354: 	ZEND_ARG_INFO(0, use_orignames)
  355: ZEND_END_ARG_INFO()
  356: 
  357: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_walk, 0, 0, 4)
  358: 	ZEND_ARG_INFO(0, object_id)
  359: 	ZEND_ARG_INFO(0, suffix_keys)
  360: 	ZEND_ARG_INFO(0, max_repetitions)
  361: 	ZEND_ARG_INFO(0, non_repeaters)
  362: ZEND_END_ARG_INFO()
  363: 
  364: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set, 0, 0, 3)
  365: 	ZEND_ARG_INFO(0, object_id)
  366: 	ZEND_ARG_INFO(0, type)
  367: 	ZEND_ARG_INFO(0, value)
  368: ZEND_END_ARG_INFO()
  369: 
  370: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_class_set_quick_print, 0, 0, 1)
  371: 	ZEND_ARG_INFO(0, quick_print)
  372: ZEND_END_ARG_INFO()
  373: /* }}} */
  374: 
  375: struct objid_query {
  376: 	int count;
  377: 	int offset;
  378: 	int step;
  379: 	long non_repeaters;
  380: 	long max_repetitions;
  381: 	int valueretrieval;
  382: 	int array_output;
  383: 	int oid_increasing_check;
  384: 	snmpobjarg *vars;
  385: };
  386: 
  387: /* {{{ snmp_functions[]
  388:  */
  389: const zend_function_entry snmp_functions[] = {
  390: 	PHP_FE(snmpget,					arginfo_snmpget)
  391: 	PHP_FE(snmpgetnext, 				arginfo_snmpgetnext)
  392: 	PHP_FE(snmpwalk, 				arginfo_snmpwalk)
  393: 	PHP_FE(snmprealwalk, 				arginfo_snmprealwalk)
  394: 	PHP_FALIAS(snmpwalkoid, snmprealwalk, 		arginfo_snmprealwalk)
  395: 	PHP_FE(snmpset, 				arginfo_snmpset)
  396: 	PHP_FE(snmp_get_quick_print, 			arginfo_snmp_get_quick_print)
  397: 	PHP_FE(snmp_set_quick_print, 			arginfo_snmp_set_quick_print)
  398: 	PHP_FE(snmp_set_enum_print, 			arginfo_snmp_set_enum_print)
  399: 	PHP_FE(snmp_set_oid_output_format, 		arginfo_snmp_set_oid_output_format)
  400: 	PHP_FALIAS(snmp_set_oid_numeric_print, snmp_set_oid_output_format, arginfo_snmp_set_oid_output_format)
  401: 
  402: 	PHP_FE(snmp2_get, 				arginfo_snmp2_get)
  403: 	PHP_FE(snmp2_getnext, 				arginfo_snmp2_getnext)
  404: 	PHP_FE(snmp2_walk, 				arginfo_snmp2_walk)
  405: 	PHP_FE(snmp2_real_walk, 			arginfo_snmp2_real_walk)
  406: 	PHP_FE(snmp2_set, 				arginfo_snmp2_set)
  407: 
  408: 	PHP_FE(snmp3_get, 				arginfo_snmp3_get)
  409: 	PHP_FE(snmp3_getnext, 				arginfo_snmp3_getnext)
  410: 	PHP_FE(snmp3_walk, 				arginfo_snmp3_walk)
  411: 	PHP_FE(snmp3_real_walk, 			arginfo_snmp3_real_walk)
  412: 	PHP_FE(snmp3_set, 				arginfo_snmp3_set)
  413: 	PHP_FE(snmp_set_valueretrieval,			arginfo_snmp_set_valueretrieval)
  414: 	PHP_FE(snmp_get_valueretrieval,			arginfo_snmp_get_valueretrieval)
  415: 
  416: 	PHP_FE(snmp_read_mib, 				arginfo_snmp_read_mib)
  417: 	PHP_FE_END
  418: };
  419: /* }}} */
  420: 
  421: /* query an agent with GET method */
  422: #define SNMP_CMD_GET		(1<<0)
  423: /* query an agent with GETNEXT method */
  424: #define SNMP_CMD_GETNEXT	(1<<1)
  425: /* query an agent with SET method */
  426: #define SNMP_CMD_SET		(1<<2)
  427: /* walk the mib */
  428: #define SNMP_CMD_WALK		(1<<3)
  429: /* force values-only output */
  430: #define SNMP_NUMERIC_KEYS	(1<<7)
  431: /* use user-supplied OID names for keys in array output mode in GET method */
  432: #define SNMP_ORIGINAL_NAMES_AS_KEYS	(1<<8)
  433: /* use OID suffix (`index') for keys in array output mode in WALK  method */
  434: #define SNMP_USE_SUFFIX_AS_KEYS	(1<<9)
  435: 
  436: #ifdef COMPILE_DL_SNMP
  437: ZEND_GET_MODULE(snmp)
  438: #endif
  439: 
  440: /* THREAD_LS snmp_module php_snmp_module; - may need one of these at some point */
  441: 
  442: /* {{{ PHP_GINIT_FUNCTION
  443:  */
  444: static PHP_GINIT_FUNCTION(snmp)
  445: {
  446: 	snmp_globals->valueretrieval = SNMP_VALUE_LIBRARY;
  447: }
  448: /* }}} */
  449: 
  450: #define PHP_SNMP_SESSION_FREE(a) { \
  451: 	if ((*session)->a) { \
  452: 		efree((*session)->a); \
  453: 		(*session)->a = NULL; \
  454: 	} \
  455: }
  456: 
  457: static void netsnmp_session_free(php_snmp_session **session)
  458: {
  459: 	if (*session) {
  460: 		PHP_SNMP_SESSION_FREE(peername);
  461: 		PHP_SNMP_SESSION_FREE(community);
  462: 		PHP_SNMP_SESSION_FREE(securityName);
  463: 		PHP_SNMP_SESSION_FREE(contextEngineID);
  464: 		efree(*session);
  465: 		*session = NULL;
  466: 	}
  467: }
  468: 
  469: static void php_snmp_session_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  470: {
  471: 	php_snmp_session *session = (php_snmp_session *)rsrc->ptr;
  472: 	netsnmp_session_free(&session);
  473: }
  474: 
  475: static void php_snmp_object_free_storage(void *object TSRMLS_DC)
  476: {
  477: 	php_snmp_object *intern = (php_snmp_object *)object;
  478: 	
  479: 	if (!intern) {
  480: 		return;
  481: 	}
  482: 
  483: 	netsnmp_session_free(&(intern->session));
  484: 
  485: 	zend_object_std_dtor(&intern->zo TSRMLS_CC);
  486: 	
  487: 	efree(intern);
  488: }
  489: 
  490: static zend_object_value php_snmp_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
  491: {
  492: 	zend_object_value retval;
  493: 	php_snmp_object *intern;
  494: 
  495: 	/* Allocate memory for it */
  496: 	intern = emalloc(sizeof(php_snmp_object));
  497: 	memset(&intern->zo, 0, sizeof(php_snmp_object));
  498: 
  499: 	zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
  500: 	object_properties_init(&intern->zo, class_type);
  501: 
  502: 	retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) php_snmp_object_free_storage, NULL TSRMLS_CC);
  503: 	retval.handlers = (zend_object_handlers *) &php_snmp_object_handlers;
  504: 
  505: 	return retval;
  506: 	
  507: }
  508: 
  509: /* {{{ php_snmp_error
  510:  *
  511:  * Record last SNMP-related error in object
  512:  *
  513:  */
  514: static void php_snmp_error(zval *object, const char *docref TSRMLS_DC, int type, const char *format, ...)
  515: {
  516: 	va_list args;
  517: 	php_snmp_object *snmp_object;
  518: 
  519: 	if (object) {
  520: 		snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
  521: 		if (type == PHP_SNMP_ERRNO_NOERROR) {
  522: 			memset(snmp_object->snmp_errstr, 0, sizeof(snmp_object->snmp_errstr));
  523: 		} else {
  524: 			va_start(args, format);
  525: 			vsnprintf(snmp_object->snmp_errstr, sizeof(snmp_object->snmp_errstr) - 1, format, args);
  526: 			va_end(args);
  527: 		}
  528: 		snmp_object->snmp_errno = type;
  529: 	}
  530: 
  531: 	if (type == PHP_SNMP_ERRNO_NOERROR) {
  532: 		return;
  533: 	}
  534: 
  535: 	if (object && (snmp_object->exceptions_enabled & type)) {
  536: 		zend_throw_exception_ex(php_snmp_exception_ce, type, snmp_object->snmp_errstr TSRMLS_CC);
  537: 	} else {
  538: 		va_start(args, format);
  539: 		php_verror(docref, "", E_WARNING, format, args TSRMLS_CC);
  540: 		va_end(args);
  541: 	}
  542: }
  543: 
  544: /* }}} */
  545: 
  546: /* {{{ php_snmp_getvalue
  547: *
  548: * SNMP value to zval converter
  549: *
  550: */
  551: static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_DC, int valueretrieval)
  552: {
  553: 	zval *val;
  554: #ifdef BUGGY_SNMPRINT_VALUE
  555: 	char sbuf[2048];
  556: #else
  557: 	char sbuf[64];
  558: #endif
  559: 	char *buf = &(sbuf[0]);
  560: 	char *dbuf = (char *)NULL;
  561: 	int buflen = sizeof(sbuf) - 1;
  562: 	int val_len = vars->val_len;
  563: 	
  564: 	if ((valueretrieval & SNMP_VALUE_PLAIN) == 0) {
  565: 		val_len += 32; /* snprint_value will add type info into value, make some space for it */
  566: 	}
  567: 
  568: 	/* use emalloc() for large values, use static array otherwize */
  569: 	if(val_len > buflen){
  570: 		if ((dbuf = (char *)emalloc(val_len + 1))) {
  571: 			buf = dbuf;
  572: 			buflen = val_len;
  573: 		} else {
  574: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed: %s, fallback to static array", strerror(errno));
  575: 		}
  576: 	}
  577: 
  578: 	*buf = 0;
  579: 
  580: 	MAKE_STD_ZVAL(val);
  581: 
  582: 	if (valueretrieval & SNMP_VALUE_PLAIN) {
  583: 		switch (vars->type) {
  584: 		case ASN_BIT_STR:		/* 0x03, asn1.h */
  585: 			ZVAL_STRINGL(val, (char *)vars->val.bitstring, vars->val_len, 1);
  586: 			break;
  587: 
  588: 		case ASN_OCTET_STR:		/* 0x04, asn1.h */
  589: 		case ASN_OPAQUE:		/* 0x44, snmp_impl.h */
  590: 			ZVAL_STRINGL(val, (char *)vars->val.string, vars->val_len, 1);
  591: 			break;
  592: 
  593: 		case ASN_NULL:			/* 0x05, asn1.h */
  594: 			ZVAL_NULL(val);
  595: 			break;
  596: 
  597: 		case ASN_OBJECT_ID:		/* 0x06, asn1.h */
  598: 			snprint_objid(buf, buflen, vars->val.objid, vars->val_len / sizeof(oid));
  599: 			ZVAL_STRING(val, buf, 1);
  600: 			break;
  601: 
  602: 		case ASN_IPADDRESS:		/* 0x40, snmp_impl.h */
  603: 			snprintf(buf, buflen, "%d.%d.%d.%d",
  604: 				 (vars->val.string)[0], (vars->val.string)[1],
  605: 				 (vars->val.string)[2], (vars->val.string)[3]);
  606: 			buf[buflen]=0;
  607: 			ZVAL_STRING(val, buf, 1);
  608: 			break;
  609: 
  610: 		case ASN_COUNTER:		/* 0x41, snmp_impl.h */
  611: 		case ASN_GAUGE:			/* 0x42, snmp_impl.h */
  612: 		/* ASN_UNSIGNED is the same as ASN_GAUGE */
  613: 		case ASN_TIMETICKS:		/* 0x43, snmp_impl.h */
  614: 		case ASN_UINTEGER:		/* 0x47, snmp_impl.h */
  615: 			snprintf(buf, buflen, "%lu", *vars->val.integer);
  616: 			buf[buflen]=0;
  617: 			ZVAL_STRING(val, buf, 1);
  618: 			break;
  619: 
  620: 		case ASN_INTEGER:		/* 0x02, asn1.h */
  621: 			snprintf(buf, buflen, "%ld", *vars->val.integer);
  622: 			buf[buflen]=0;
  623: 			ZVAL_STRING(val, buf, 1);
  624: 			break;
  625: 
  626: #if defined(NETSNMP_WITH_OPAQUE_SPECIAL_TYPES) || defined(OPAQUE_SPECIAL_TYPES)
  627: 		case ASN_OPAQUE_FLOAT:		/* 0x78, asn1.h */
  628: 			snprintf(buf, buflen, "%f", *vars->val.floatVal);
  629: 			ZVAL_STRING(val, buf, 1);
  630: 			break;
  631: 
  632: 		case ASN_OPAQUE_DOUBLE:		/* 0x79, asn1.h */
  633: 			snprintf(buf, buflen, "%Lf", *vars->val.doubleVal);
  634: 			ZVAL_STRING(val, buf, 1);
  635: 			break;
  636: 
  637: 		case ASN_OPAQUE_I64:		/* 0x80, asn1.h */
  638: 			printI64(buf, vars->val.counter64);
  639: 			ZVAL_STRING(val, buf, 1);
  640: 			break;
  641: 
  642: 		case ASN_OPAQUE_U64:		/* 0x81, asn1.h */
  643: #endif
  644: 		case ASN_COUNTER64:		/* 0x46, snmp_impl.h */
  645: 			printU64(buf, vars->val.counter64);
  646: 			ZVAL_STRING(val, buf, 1);
  647: 			break;
  648: 
  649: 		default:
  650: 			ZVAL_STRING(val, "Unknown value type", 1);
  651: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown value type: %u", vars->type);
  652: 			break;
  653: 		}
  654: 	} else /* use Net-SNMP value translation */ {
  655: 		snprint_value(buf, buflen, vars->name, vars->name_length, vars);
  656: 		ZVAL_STRING(val, buf, 1);
  657: 	}
  658: 
  659: 	if (valueretrieval & SNMP_VALUE_OBJECT) {
  660: 		object_init(snmpval);
  661: 		add_property_long(snmpval, "type", vars->type);
  662: 		add_property_zval(snmpval, "value", val);
  663: 	} else  {
  664: 		*snmpval = *val;
  665: 		zval_copy_ctor(snmpval);
  666: 	}
  667: 	zval_ptr_dtor(&val);
  668: 
  669: 	if(dbuf){ /* malloc was used to store value */
  670: 		efree(dbuf);
  671: 	}
  672: }
  673: /* }}} */
  674: 
  675: /* {{{ php_snmp_internal
  676: *
  677: * SNMP object fetcher/setter for all SNMP versions
  678: *
  679: */
  680: static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, 
  681: 							struct snmp_session *session,
  682: 							struct objid_query *objid_query)
  683: {
  684: 	struct snmp_session *ss;
  685: 	struct snmp_pdu *pdu=NULL, *response;
  686: 	struct variable_list *vars;
  687: 	oid root[MAX_NAME_LEN];
  688: 	size_t rootlen = 0;
  689: 	int status, count, found;
  690: 	char buf[2048];
  691: 	char buf2[2048];
  692: 	int keepwalking=1;
  693: 	char *err;
  694: 	zval *snmpval = NULL;
  695: 	int snmp_errno;
  696: 
  697: 	/* we start with retval=FALSE. If any actual data is aquired, retval will be set to appropriate type */
  698: 	RETVAL_FALSE;
  699: 	
  700: 	/* reset errno and errstr */
  701: 	php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_NOERROR, "");
  702: 
  703: 	if (st & SNMP_CMD_WALK) { /* remember root OID */
  704: 		memmove((char *)root, (char *)(objid_query->vars[0].name), (objid_query->vars[0].name_length) * sizeof(oid));
  705: 		rootlen = objid_query->vars[0].name_length;
  706: 		objid_query->offset = objid_query->count;
  707: 	}
  708: 
  709: 	if ((ss = snmp_open(session)) == NULL) {
  710: 		snmp_error(session, NULL, NULL, &err);
  711: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open snmp connection: %s", err);
  712: 		free(err);
  713: 		RETVAL_FALSE;
  714: 		return;
  715: 	}
  716: 
  717: 	if ((st & SNMP_CMD_SET) && objid_query->count > objid_query->step) {
  718: 		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");
  719: 	}
  720: 
  721: 	while (keepwalking) {
  722: 		keepwalking = 0;
  723: 		if (st & SNMP_CMD_WALK) {
  724: 			if (session->version == SNMP_VERSION_1) {
  725: 				pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
  726: 			} else {
  727: 				pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
  728: 				pdu->non_repeaters = objid_query->non_repeaters;
  729: 				pdu->max_repetitions = objid_query->max_repetitions;
  730: 			}
  731: 			snmp_add_null_var(pdu, objid_query->vars[0].name, objid_query->vars[0].name_length);
  732: 		} else {
  733: 			if (st & SNMP_CMD_GET) {
  734: 				pdu = snmp_pdu_create(SNMP_MSG_GET);
  735: 			} else if (st & SNMP_CMD_GETNEXT) {
  736: 				pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
  737: 			} else if (st & SNMP_CMD_SET) {
  738: 				pdu = snmp_pdu_create(SNMP_MSG_SET);
  739: 			} else {
  740: 				snmp_close(ss);
  741: 				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unknown SNMP command (internals)");
  742: 				RETVAL_FALSE;
  743: 				return;
  744: 			}
  745: 			for (count = 0; objid_query->offset < objid_query->count && count < objid_query->step; objid_query->offset++, count++){
  746: 				if (st & SNMP_CMD_SET) {
  747: 					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))) {
  748: 						snprint_objid(buf, sizeof(buf), objid_query->vars[objid_query->offset].name, objid_query->vars[objid_query->offset].name_length);
  749: 						php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Could not add variable: OID='%s' type='%c' value='%s': %s", buf, objid_query->vars[objid_query->offset].type, objid_query->vars[objid_query->offset].value, snmp_api_errstring(snmp_errno));
  750: 						snmp_free_pdu(pdu);
  751: 						snmp_close(ss);
  752: 						RETVAL_FALSE;
  753: 						return;
  754: 					}
  755: 				} else {
  756: 					snmp_add_null_var(pdu, objid_query->vars[objid_query->offset].name, objid_query->vars[objid_query->offset].name_length);
  757: 				}
  758: 			}
  759: 			if(pdu->variables == NULL){
  760: 				snmp_free_pdu(pdu);
  761: 				snmp_close(ss);
  762: 				RETVAL_FALSE;
  763: 				return;
  764: 			}
  765: 		}
  766: 
  767: retry:
  768: 		status = snmp_synch_response(ss, pdu, &response);
  769: 		if (status == STAT_SUCCESS) {
  770: 			if (response->errstat == SNMP_ERR_NOERROR) {
  771: 				if (st & SNMP_CMD_SET) {
  772: 					if (objid_query->offset < objid_query->count) { /* we have unprocessed OIDs */
  773: 						keepwalking = 1;
  774: 						continue;
  775: 					}
  776: 					snmp_free_pdu(response);
  777: 					snmp_close(ss);
  778: 					RETVAL_TRUE;
  779: 					return;
  780: 				}
  781: 				for (vars = response->variables; vars; vars = vars->next_variable) {
  782: 					/* do not output errors as values */
  783: 					if ( 	vars->type == SNMP_ENDOFMIBVIEW || 
  784: 						vars->type == SNMP_NOSUCHOBJECT || 
  785: 						vars->type == SNMP_NOSUCHINSTANCE ) {
  786: 						if ((st & SNMP_CMD_WALK) && Z_TYPE_P(return_value) == IS_ARRAY) {
  787: 							break;
  788: 						}
  789: 						snprint_objid(buf, sizeof(buf), vars->name, vars->name_length);
  790: 						snprint_value(buf2, sizeof(buf2), vars->name, vars->name_length, vars);
  791: 						php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_ERROR_IN_REPLY, "Error in packet at '%s': %s", buf, buf2);
  792: 						continue;
  793: 					}
  794: 					
  795: 					if ((st & SNMP_CMD_WALK) && 
  796: 						(vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid)))) { /* not part of this subtree */
  797: 						if (Z_TYPE_P(return_value) == IS_ARRAY) { /* some records are fetched already, shut down further lookup */
  798: 							keepwalking = 0;
  799: 						} else {
  800: 							/* first fetched OID is out of subtree, fallback to GET query */
  801: 							st |= SNMP_CMD_GET;
  802: 							st ^= SNMP_CMD_WALK;
  803: 							objid_query->offset = 0;
  804: 							keepwalking = 1;
  805: 						}
  806: 						break;
  807: 					}
  808: 
  809: 					MAKE_STD_ZVAL(snmpval);
  810: 					php_snmp_getvalue(vars, snmpval TSRMLS_CC, objid_query->valueretrieval);
  811: 
  812: 					if (objid_query->array_output) {
  813: 						if (Z_TYPE_P(return_value) == IS_BOOL) {
  814: 							array_init(return_value);
  815: 						}
  816: 						if (st & SNMP_NUMERIC_KEYS) {
  817: 							add_next_index_zval(return_value, snmpval);
  818: 						} else if (st & SNMP_ORIGINAL_NAMES_AS_KEYS && st & SNMP_CMD_GET) {
  819: 							found = 0;
  820: 							for (count = 0; count < objid_query->count; count++) {
  821: 								if (objid_query->vars[count].name_length == vars->name_length && snmp_oid_compare(objid_query->vars[count].name, objid_query->vars[count].name_length, vars->name, vars->name_length) == 0) {
  822: 									found = 1;
  823: 									objid_query->vars[count].name_length = 0; /* mark this name as used */
  824: 									break;
  825: 								}
  826: 							}
  827: 							if (found) {
  828: 								add_assoc_zval(return_value, objid_query->vars[count].oid, snmpval);
  829: 							} else {
  830: 								snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
  831: 								php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find original OID name for '%s'", buf2);
  832: 							}
  833: 						} else if (st & SNMP_USE_SUFFIX_AS_KEYS && st & SNMP_CMD_WALK) {
  834: 							snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
  835: 							if (objid_query->vars[0].name_length <= vars->name_length && snmp_oid_compare(objid_query->vars[0].name, objid_query->vars[0].name_length, vars->name, objid_query->vars[0].name_length) == 0) {
  836: 								buf2[0] = '\0';
  837: 								count = objid_query->vars[0].name_length;
  838: 								while(count < vars->name_length){
  839: 									sprintf(buf, "%lu.", vars->name[count]);
  840: 									strcat(buf2, buf);
  841: 									count++;
  842: 								}
  843: 								buf2[strlen(buf2) - 1] = '\0'; /* remove trailing '.' */
  844: 							}
  845: 							add_assoc_zval(return_value, buf2, snmpval);
  846: 						} else {
  847: 							snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
  848: 							add_assoc_zval(return_value, buf2, snmpval);
  849: 						}
  850: 					} else {
  851: 						*return_value = *snmpval;
  852: 						zval_copy_ctor(return_value);
  853: 						zval_ptr_dtor(&snmpval);
  854: 						break;
  855: 					}
  856: 
  857: 					/* OID increase check */
  858: 					if (st & SNMP_CMD_WALK) {
  859: 						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) {
  860: 							snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
  861: 							php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_NOT_INCREASING, "Error: OID not increasing: %s", buf2);
  862: 							keepwalking = 0;
  863: 						} else {
  864: 							memmove((char *)(objid_query->vars[0].name), (char *)vars->name, vars->name_length * sizeof(oid));
  865: 							objid_query->vars[0].name_length = vars->name_length;
  866: 							keepwalking = 1;
  867: 						}
  868: 					}
  869: 				}
  870: 				if (objid_query->offset < objid_query->count) { /* we have unprocessed OIDs */
  871: 					keepwalking = 1;
  872: 				}
  873: 			} else {
  874: 				if (!(st & SNMP_CMD_WALK) || response->errstat != SNMP_ERR_NOSUCHNAME || Z_TYPE_P(return_value) == IS_BOOL) {
  875: 					for (	count=1, vars = response->variables;
  876: 						vars && count != response->errindex;
  877: 						vars = vars->next_variable, count++);
  878: 
  879: 					if (st & (SNMP_CMD_GET | SNMP_CMD_GETNEXT) && response->errstat == SNMP_ERR_TOOBIG && objid_query->step > 1) { /* Answer will not fit into single packet */
  880: 						objid_query->offset = ((objid_query->offset > objid_query->step) ? (objid_query->offset - objid_query->step) : 0 );
  881: 						objid_query->step /= 2;
  882: 						snmp_free_pdu(response);
  883: 						keepwalking = 1;
  884: 						continue;
  885: 					}
  886: 					if (vars) {
  887: 						snprint_objid(buf, sizeof(buf), vars->name, vars->name_length);
  888: 						php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_ERROR_IN_REPLY, "Error in packet at '%s': %s", buf, snmp_errstring(response->errstat));
  889: 					} else {
  890: 						php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_ERROR_IN_REPLY, "Error in packet at %u object_id: %s", response->errindex, snmp_errstring(response->errstat));
  891: 					}
  892: 					if (st & (SNMP_CMD_GET | SNMP_CMD_GETNEXT)) { /* cut out bogus OID and retry */
  893: 						if ((pdu = snmp_fix_pdu(response, ((st & SNMP_CMD_GET) ? SNMP_MSG_GET : SNMP_MSG_GETNEXT) )) != NULL) {
  894: 							snmp_free_pdu(response);
  895: 							goto retry;
  896: 						}
  897: 					}
  898: 					snmp_free_pdu(response);
  899: 					snmp_close(ss);
  900: 					if (objid_query->array_output) {
  901: 						zval_dtor(return_value);
  902: 					}
  903: 					RETVAL_FALSE;
  904: 					return;
  905: 				}
  906: 			}
  907: 		} else if (status == STAT_TIMEOUT) {
  908: 			php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_TIMEOUT, "No response from %s", session->peername);
  909: 			if (objid_query->array_output) {
  910: 				zval_dtor(return_value);
  911: 			}
  912: 			snmp_close(ss);
  913: 			RETVAL_FALSE;
  914: 			return;
  915: 		} else {    /* status == STAT_ERROR */
  916: 			snmp_error(ss, NULL, NULL, &err);
  917: 			php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_GENERIC, "Fatal error: %s", err);
  918: 			free(err);
  919: 			if (objid_query->array_output) {
  920: 				zval_dtor(return_value);
  921: 			}
  922: 			snmp_close(ss);
  923: 			RETVAL_FALSE;
  924: 			return;
  925: 		}
  926: 		if (response) {
  927: 			snmp_free_pdu(response);
  928: 		}
  929: 	} /* keepwalking */
  930: 	snmp_close(ss);
  931: }
  932: /* }}} */
  933: 
  934: /* {{{ php_snmp_parse_oid
  935: *
  936: * OID parser (and type, value for SNMP_SET command)
  937: */
  938: 
  939: static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_query, zval **oid, zval **type, zval **value TSRMLS_DC)
  940: {
  941: 	char *pptr;
  942: 	HashPosition pos_oid, pos_type, pos_value;
  943: 	zval **tmp_oid, **tmp_type, **tmp_value;
  944: 
  945: 	if (Z_TYPE_PP(oid) != IS_ARRAY) {
  946: 		if (Z_ISREF_PP(oid)) {
  947: 			SEPARATE_ZVAL(oid);
  948: 		}
  949: 		convert_to_string_ex(oid);
  950: 	} else if (Z_TYPE_PP(oid) == IS_ARRAY) {
  951: 		zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(oid), &pos_oid);
  952: 	}
  953: 
  954: 	if (st & SNMP_CMD_SET) {
  955: 		if (Z_TYPE_PP(type) != IS_ARRAY) {
  956: 			if (Z_ISREF_PP(type)) {
  957: 				SEPARATE_ZVAL(type);
  958: 			}
  959: 			convert_to_string_ex(type);
  960: 		} else if (Z_TYPE_PP(type) == IS_ARRAY) {
  961: 			zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(type), &pos_type);
  962: 		}
  963: 
  964: 		if (Z_TYPE_PP(value) != IS_ARRAY) {
  965: 			if (Z_ISREF_PP(value)) {
  966: 				SEPARATE_ZVAL(value);
  967: 			}
  968: 			convert_to_string_ex(value);
  969: 		} else if (Z_TYPE_PP(value) == IS_ARRAY) {
  970: 			zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(value), &pos_value);
  971: 		}
  972: 	}
  973: 
  974: 	objid_query->count = 0;
  975: 	objid_query->array_output = ((st & SNMP_CMD_WALK) ? TRUE : FALSE);
  976: 	if (Z_TYPE_PP(oid) == IS_STRING) {
  977: 		objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg));
  978: 		if (objid_query->vars == NULL) {
  979: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while parsing oid: %s", strerror(errno));
  980: 			efree(objid_query->vars);
  981: 			return FALSE;
  982: 		}
  983: 		objid_query->vars[objid_query->count].oid = Z_STRVAL_PP(oid);
  984: 		if (st & SNMP_CMD_SET) {
  985: 			if (Z_TYPE_PP(type) == IS_STRING && Z_TYPE_PP(value) == IS_STRING) {
  986: 				if (Z_STRLEN_PP(type) != 1) {
  987: 					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bogus type '%s', should be single char, got %u", Z_STRVAL_PP(type), Z_STRLEN_PP(type));
  988: 					efree(objid_query->vars);
  989: 					return FALSE;
  990: 				}
  991: 				pptr = Z_STRVAL_PP(type);
  992: 				objid_query->vars[objid_query->count].type = *pptr;
  993: 				objid_query->vars[objid_query->count].value = Z_STRVAL_PP(value);
  994: 			} else {
  995: 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Single objid and multiple type or values are not supported");
  996: 				efree(objid_query->vars);
  997: 				return FALSE;
  998: 			}
  999: 		}
 1000: 		objid_query->count++;
 1001: 	} else if (Z_TYPE_PP(oid) == IS_ARRAY) { /* we got objid array */
 1002: 		if (zend_hash_num_elements(Z_ARRVAL_PP(oid)) == 0) {
 1003: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Got empty OID array");
 1004: 			return FALSE;
 1005: 		}
 1006: 		objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_PP(oid)));
 1007: 		if (objid_query->vars == NULL) {
 1008: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno));
 1009: 			efree(objid_query->vars);
 1010: 			return FALSE;
 1011: 		}
 1012: 		objid_query->array_output = ( (st & SNMP_CMD_SET) ? FALSE : TRUE );
 1013: 		for (	zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(oid), &pos_oid);
 1014: 			zend_hash_get_current_data_ex(Z_ARRVAL_PP(oid), (void **) &tmp_oid, &pos_oid) == SUCCESS;
 1015: 			zend_hash_move_forward_ex(Z_ARRVAL_PP(oid), &pos_oid) ) {
 1016: 
 1017: 			convert_to_string_ex(tmp_oid);
 1018: 			objid_query->vars[objid_query->count].oid = Z_STRVAL_PP(tmp_oid);
 1019: 			if (st & SNMP_CMD_SET) {
 1020: 				if (Z_TYPE_PP(type) == IS_STRING) {
 1021: 					pptr = Z_STRVAL_PP(type);
 1022: 					objid_query->vars[objid_query->count].type = *pptr;
 1023: 				} else if (Z_TYPE_PP(type) == IS_ARRAY) {
 1024: 					if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(type), (void **) &tmp_type, &pos_type)) {
 1025: 						convert_to_string_ex(tmp_type);
 1026: 						if (Z_STRLEN_PP(tmp_type) != 1) {
 1027: 							php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s': bogus type '%s', should be single char, got %u", Z_STRVAL_PP(tmp_oid), Z_STRVAL_PP(tmp_type), Z_STRLEN_PP(tmp_type));
 1028: 							efree(objid_query->vars);
 1029: 							return FALSE;
 1030: 						}
 1031: 						pptr = Z_STRVAL_PP(tmp_type);
 1032: 						objid_query->vars[objid_query->count].type = *pptr;
 1033: 						zend_hash_move_forward_ex(Z_ARRVAL_PP(type), &pos_type);
 1034: 					} else {
 1035: 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s': no type set", Z_STRVAL_PP(tmp_oid));
 1036: 						efree(objid_query->vars);
 1037: 						return FALSE;
 1038: 					}
 1039: 				}
 1040: 
 1041: 				if (Z_TYPE_PP(value) == IS_STRING) {
 1042: 					objid_query->vars[objid_query->count].value = Z_STRVAL_PP(value);
 1043: 				} else if (Z_TYPE_PP(value) == IS_ARRAY) {
 1044: 					if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(value), (void **) &tmp_value, &pos_value)) {
 1045: 						convert_to_string_ex(tmp_value);
 1046: 						objid_query->vars[objid_query->count].value = Z_STRVAL_PP(tmp_value);
 1047: 						zend_hash_move_forward_ex(Z_ARRVAL_PP(value), &pos_value);
 1048: 					} else {
 1049: 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s': no value set", Z_STRVAL_PP(tmp_oid));
 1050: 						efree(objid_query->vars);
 1051: 						return FALSE;
 1052: 					}
 1053: 				}
 1054: 			}
 1055: 			objid_query->count++;
 1056: 		}
 1057: 	}
 1058: 
 1059: 	/* now parse all OIDs */
 1060: 	if (st & SNMP_CMD_WALK) {
 1061: 		if (objid_query->count > 1) {
 1062: 			php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Multi OID walks are not supported!");
 1063: 			efree(objid_query->vars);
 1064: 			return FALSE;
 1065: 		}
 1066: 		objid_query->vars[0].name_length = MAX_NAME_LEN;
 1067: 		if (strlen(objid_query->vars[0].oid)) { /* on a walk, an empty string means top of tree - no error */
 1068: 			if (!snmp_parse_oid(objid_query->vars[0].oid, objid_query->vars[0].name, &(objid_query->vars[0].name_length))) {
 1069: 				php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[0].oid);
 1070: 				efree(objid_query->vars);
 1071: 				return FALSE;
 1072: 			}
 1073: 		} else { 
 1074: 			memmove((char *)objid_query->vars[0].name, (char *)objid_mib, sizeof(objid_mib));
 1075: 			objid_query->vars[0].name_length = sizeof(objid_mib) / sizeof(oid);
 1076: 		}
 1077: 	} else {
 1078: 		for (objid_query->offset = 0; objid_query->offset < objid_query->count; objid_query->offset++) {
 1079: 			objid_query->vars[objid_query->offset].name_length = MAX_OID_LEN;
 1080: 			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))) {
 1081: 				php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[objid_query->offset].oid);
 1082: 				efree(objid_query->vars);
 1083: 				return FALSE;
 1084: 			}
 1085: 		}
 1086: 	}
 1087: 	objid_query->offset = 0;
 1088: 	objid_query->step = objid_query->count;
 1089: 	return (objid_query->count > 0);
 1090: }
 1091: /* }}} */
 1092: 
 1093: /* {{{ netsnmp_session_init
 1094: 	allocates memory for session and session->peername, caller should free it manually using netsnmp_session_free() and efree()
 1095: */
 1096: static int netsnmp_session_init(php_snmp_session **session_p, int version, char *hostname, char *community, int timeout, int retries TSRMLS_DC)
 1097: {
 1098: 	php_snmp_session *session;
 1099: 	char *pptr;
 1100: 	char buf[MAX_NAME_LEN];
 1101: 	int force_ipv6 = FALSE;
 1102: 	int n;
 1103: 	struct sockaddr **psal;
 1104: 	struct sockaddr **res;
 1105: 
 1106: 	*session_p = (php_snmp_session *)emalloc(sizeof(php_snmp_session));
 1107: 	session = *session_p;
 1108: 	if (session == NULL) {
 1109: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed allocating session");
 1110: 		return (-1);
 1111: 	}
 1112: 	memset(session, 0, sizeof(php_snmp_session));
 1113: 
 1114: 	strlcpy(buf, hostname, sizeof(buf));
 1115: 
 1116: 	snmp_sess_init(session);
 1117: 
 1118: 	session->version = version;
 1119: 	session->remote_port = SNMP_PORT;
 1120: 
 1121: 	session->peername = emalloc(MAX_NAME_LEN);
 1122: 	if (session->peername == NULL) {
 1123: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while copying hostname");
 1124: 		return (-1);
 1125: 	}
 1126: 	*(session->peername) = '\0';
 1127: 
 1128: 	/* Reading the hostname and its optional non-default port number */
 1129: 	if (*hostname == '[') { /* IPv6 address */
 1130: 		force_ipv6 = TRUE;
 1131: 		hostname++;
 1132: 		if ((pptr = strchr(hostname, ']'))) {
 1133: 			if (pptr[1] == ':') {
 1134: 				session->remote_port = atoi(pptr + 2);
 1135: 			}
 1136: 			*pptr = '\0';
 1137: 		} else {
 1138: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "mailformed IPv6 address, closing square bracket missing");
 1139: 			return (-1);
 1140: 		}
 1141: 	} else { /* IPv4 address */
 1142: 		if ((pptr = strchr(hostname, ':'))) {
 1143: 			session->remote_port = atoi(pptr + 1);
 1144: 			*pptr = '\0';
 1145: 		}
 1146: 	}
 1147: 
 1148: 	/* since Net-SNMP library requires 'udp6:' prefix for all IPv6 addresses (in FQDN form too) we need to
 1149: 	   perform possible name resolution before running any SNMP queries */
 1150: 	if ((n = php_network_getaddresses(hostname, SOCK_DGRAM, &psal, NULL TSRMLS_CC)) == 0) { /* some resover error */
 1151: 		/* warnings sent, bailing out */
 1152: 		return (-1);
 1153: 	}
 1154: 
 1155: 	res = psal;
 1156: 	while (n-- > 0) {
 1157: 		pptr = session->peername;
 1158: #if HAVE_GETADDRINFO && HAVE_IPV6 && HAVE_INET_NTOP
 1159: 		if (force_ipv6 && (*res)->sa_family != AF_INET6) {
 1160: 			res++;
 1161: 			continue;
 1162: 		}
 1163: 		if ((*res)->sa_family == AF_INET6) {
 1164: 			strcpy(session->peername, "udp6:");
 1165: 			pptr = session->peername + strlen(session->peername);
 1166: 			inet_ntop((*res)->sa_family, &(((struct sockaddr_in6*)(*res))->sin6_addr), pptr, MAX_NAME_LEN);
 1167: 		} else if ((*res)->sa_family == AF_INET) {
 1168: 			inet_ntop((*res)->sa_family, &(((struct sockaddr_in*)(*res))->sin_addr), pptr, MAX_NAME_LEN);
 1169: 		} else {
 1170: 			res++;
 1171: 			continue;
 1172: 		}
 1173: #else
 1174: 		if ((*res)->sa_family != AF_INET) {
 1175: 			res++;
 1176: 			continue;
 1177: 		}
 1178: 		strcat(pptr, inet_ntoa(((struct sockaddr_in*)(*res))->sin_addr));
 1179: #endif
 1180: 		break;
 1181: 	}
 1182: 
 1183: 	if (strlen(session->peername) == 0) {
 1184: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown failure while resolving '%s'", buf);
 1185: 		return (-1);
 1186: 	}
 1187: 	/* XXX FIXME
 1188: 		There should be check for non-empty session->peername!
 1189: 	*/
 1190: 
 1191: 	/* put back non-standard SNMP port */
 1192: 	if (session->remote_port != SNMP_PORT) {
 1193: 		pptr = session->peername + strlen(session->peername);
 1194: 		sprintf(pptr, ":%d", session->remote_port);
 1195: 	}
 1196: 
 1197: 	php_network_freeaddresses(psal);
 1198: 
 1199: 	if (version == SNMP_VERSION_3) {
 1200: 		/* Setting the security name. */
 1201: 		session->securityName = estrdup(community);
 1202: 		session->securityNameLen = strlen(session->securityName);
 1203: 	} else {
 1204: 		session->authenticator = NULL;
 1205: 		session->community = (u_char *)estrdup(community);
 1206: 		session->community_len = strlen(community);
 1207: 	}
 1208: 
 1209: 	session->retries = retries;
 1210: 	session->timeout = timeout;
 1211: 	return (0);
 1212: }
 1213: /* }}} */
 1214: 
 1215: /* {{{ int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
 1216:    Set the security level in the snmpv3 session */
 1217: static int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
 1218: {
 1219: 	if (!strcasecmp(level, "noAuthNoPriv") || !strcasecmp(level, "nanp")) {
 1220: 		s->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
 1221: 	} else if (!strcasecmp(level, "authNoPriv") || !strcasecmp(level, "anp")) {
 1222: 		s->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
 1223: 	} else if (!strcasecmp(level, "authPriv") || !strcasecmp(level, "ap")) {
 1224: 		s->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
 1225: 	} else {
 1226: 		return (-1);
 1227: 	}
 1228: 	return (0);
 1229: }
 1230: /* }}} */
 1231: 
 1232: /* {{{ int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot)
 1233:    Set the authentication protocol in the snmpv3 session */
 1234: static int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
 1235: {
 1236: 	if (!strcasecmp(prot, "MD5")) {
 1237: 		s->securityAuthProto = usmHMACMD5AuthProtocol;
 1238: 		s->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
 1239: 	} else if (!strcasecmp(prot, "SHA")) {
 1240: 		s->securityAuthProto = usmHMACSHA1AuthProtocol;
 1241: 		s->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
 1242: 	} else {
 1243: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown authentication protocol '%s'", prot);
 1244: 		return (-1);
 1245: 	}
 1246: 	return (0);
 1247: }
 1248: /* }}} */
 1249: 
 1250: /* {{{ int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot)
 1251:    Set the security protocol in the snmpv3 session */
 1252: static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
 1253: {
 1254: 	if (!strcasecmp(prot, "DES")) {
 1255: 		s->securityPrivProto = usmDESPrivProtocol;
 1256: 		s->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
 1257: #ifdef HAVE_AES
 1258: 	} else if (!strcasecmp(prot, "AES128") || !strcasecmp(prot, "AES")) {
 1259: 		s->securityPrivProto = usmAESPrivProtocol;
 1260: 		s->securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN;
 1261: #endif
 1262: 	} else {
 1263: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown security protocol '%s'", prot);
 1264: 		return (-1);
 1265: 	}
 1266: 	return (0);
 1267: }
 1268: /* }}} */
 1269: 
 1270: /* {{{ int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass)
 1271:    Make key from pass phrase in the snmpv3 session */
 1272: static int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass TSRMLS_DC)
 1273: {
 1274: 	int snmp_errno;
 1275: 	s->securityAuthKeyLen = USM_AUTH_KU_LEN;
 1276: 	if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
 1277: 			(u_char *) pass, strlen(pass),
 1278: 			s->securityAuthKey, &(s->securityAuthKeyLen)))) {
 1279: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for authentication pass phrase '%s': %s", pass, snmp_api_errstring(snmp_errno));
 1280: 		return (-1);
 1281: 	}
 1282: 	return (0);
 1283: }
 1284: /* }}} */
 1285: 
 1286: /* {{{ int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass)
 1287:    Make key from pass phrase in the snmpv3 session */
 1288: static int netsnmp_session_gen_sec_key(struct snmp_session *s, char *pass TSRMLS_DC)
 1289: {
 1290: 	int snmp_errno;
 1291: 
 1292: 	s->securityPrivKeyLen = USM_PRIV_KU_LEN;
 1293: 	if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
 1294: 			(u_char *)pass, strlen(pass),
 1295: 			s->securityPrivKey, &(s->securityPrivKeyLen)))) {
 1296: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for privacy pass phrase '%s': %s", pass, snmp_api_errstring(snmp_errno));
 1297: 		return (-2);
 1298: 	}
 1299: 	return (0);
 1300: }
 1301: /* }}} */
 1302: 
 1303: /* {{{ in netsnmp_session_set_contextEngineID(struct snmp_session *s, u_char * contextEngineID)
 1304:    Set context Engine Id in the snmpv3 session */
 1305: static int netsnmp_session_set_contextEngineID(struct snmp_session *s, char * contextEngineID TSRMLS_DC)
 1306: {
 1307: 	size_t	ebuf_len = 32, eout_len = 0;
 1308: 	u_char	*ebuf = (u_char *) emalloc(ebuf_len);
 1309: 
 1310: 	if (ebuf == NULL) {
 1311: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "malloc failure setting contextEngineID");
 1312: 		return (-1);
 1313: 	}
 1314: 	if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, contextEngineID)) {
 1315: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad engine ID value '%s'", contextEngineID);
 1316: 		efree(ebuf);
 1317: 		return (-1);
 1318: 	}
 1319: 
 1320: 	if (s->contextEngineID) {
 1321: 		efree(s->contextEngineID);
 1322: 	}
 1323: 
 1324: 	s->contextEngineID = ebuf;
 1325: 	s->contextEngineIDLen = eout_len;
 1326: 	return (0);
 1327: }
 1328: /* }}} */
 1329: 
 1330: /* {{{ php_set_security(struct snmp_session *session, char *sec_level, char *auth_protocol, char *auth_passphrase, char *priv_protocol, char *priv_passphrase, char *contextName, char *contextEngineID)
 1331:    Set all snmpv3-related security options */
 1332: static int netsnmp_session_set_security(struct snmp_session *session, char *sec_level, char *auth_protocol, char *auth_passphrase, char *priv_protocol, char *priv_passphrase, char *contextName, char *contextEngineID TSRMLS_DC)
 1333: {
 1334: 
 1335: 	/* Setting the security level. */
 1336: 	if (netsnmp_session_set_sec_level(session, sec_level)) {
 1337: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security level '%s'", sec_level);
 1338: 		return (-1);
 1339: 	}
 1340: 
 1341: 	if (session->securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
 1342: 
 1343: 		/* Setting the authentication protocol. */
 1344: 		if (netsnmp_session_set_auth_protocol(session, auth_protocol TSRMLS_CC)) {
 1345: 			/* Warning message sent already, just bail out */
 1346: 			return (-1);
 1347: 		}
 1348: 
 1349: 		/* Setting the authentication passphrase. */
 1350: 		if (netsnmp_session_gen_auth_key(session, auth_passphrase TSRMLS_CC)) {
 1351: 			/* Warning message sent already, just bail out */
 1352: 			return (-1);
 1353: 		}
 1354: 
 1355: 		if (session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
 1356: 			/* Setting the security protocol. */
 1357: 			if (netsnmp_session_set_sec_protocol(session, priv_protocol TSRMLS_CC)) {
 1358: 				/* Warning message sent already, just bail out */
 1359: 				return (-1);
 1360: 			}
 1361: 
 1362: 			/* Setting the security protocol passphrase. */
 1363: 			if (netsnmp_session_gen_sec_key(session, priv_passphrase TSRMLS_CC)) {
 1364: 				/* Warning message sent already, just bail out */
 1365: 				return (-1);
 1366: 			}
 1367: 		}
 1368: 	}
 1369: 
 1370: 	/* Setting contextName if specified */
 1371: 	if (contextName) {
 1372: 		session->contextName = contextName;
 1373: 		session->contextNameLen = strlen(contextName);
 1374: 	}
 1375: 
 1376: 	/* Setting contextEngineIS if specified */
 1377: 	if (contextEngineID && strlen(contextEngineID) && netsnmp_session_set_contextEngineID(session, contextEngineID TSRMLS_CC)) {
 1378: 		/* Warning message sent already, just bail out */
 1379: 		return (-1);
 1380: 	}
 1381: 
 1382: 	return (0);
 1383: }
 1384: /* }}} */
 1385: 
 1386: /* {{{ php_snmp
 1387: *
 1388: * Generic SNMP handler for all versions.
 1389: * This function makes use of the internal SNMP object fetcher.
 1390: * Used both in old (non-OO) and OO API
 1391: *
 1392: */
 1393: static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 1394: {
 1395: 	zval **oid, **value, **type;
 1396: 	char *a1, *a2, *a3, *a4, *a5, *a6, *a7;
 1397: 	int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len;
 1398: 	zend_bool use_orignames = 0, suffix_keys = 0;
 1399: 	long timeout = SNMP_DEFAULT_TIMEOUT;
 1400: 	long retries = SNMP_DEFAULT_RETRIES;
 1401: 	int argc = ZEND_NUM_ARGS();
 1402: 	struct objid_query objid_query;
 1403: 	php_snmp_session *session;
 1404: 	int session_less_mode = (getThis() == NULL);
 1405: 	php_snmp_object *snmp_object;
 1406: 	php_snmp_object glob_snmp_object;
 1407: 	
 1408: 	objid_query.max_repetitions = -1;
 1409: 	objid_query.non_repeaters = 0;
 1410: 	objid_query.valueretrieval = SNMP_G(valueretrieval);
 1411: 	objid_query.oid_increasing_check = TRUE;
 1412: 
 1413: 	if (session_less_mode) {
 1414: 		if (version == SNMP_VERSION_3) {
 1415: 			if (st & SNMP_CMD_SET) {
 1416: 				if (zend_parse_parameters(argc TSRMLS_CC, "sssssssZZZ|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 1417: 					&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &oid, &type, &value, &timeout, &retries) == FAILURE) {
 1418: 					RETURN_FALSE;
 1419: 				}
 1420: 			} else {
 1421: 				/* SNMP_CMD_GET
 1422: 				 * SNMP_CMD_GETNEXT
 1423: 				 * SNMP_CMD_WALK
 1424: 				 */
 1425: 				if (zend_parse_parameters(argc TSRMLS_CC, "sssssssZ|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 1426: 					&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &oid, &timeout, &retries) == FAILURE) {
 1427: 					RETURN_FALSE;
 1428: 				}
 1429: 			}
 1430: 		} else {
 1431: 			if (st & SNMP_CMD_SET) {
 1432: 				if (zend_parse_parameters(argc TSRMLS_CC, "ssZZZ|ll", &a1, &a1_len, &a2, &a2_len, &oid, &type, &value, &timeout, &retries) == FAILURE) {
 1433: 					RETURN_FALSE;
 1434: 				}
 1435: 			} else {
 1436: 				/* SNMP_CMD_GET
 1437: 				 * SNMP_CMD_GETNEXT
 1438: 				 * SNMP_CMD_WALK
 1439: 				 */
 1440: 				if (zend_parse_parameters(argc TSRMLS_CC, "ssZ|ll", &a1, &a1_len, &a2, &a2_len, &oid, &timeout, &retries) == FAILURE) {
 1441: 					RETURN_FALSE;
 1442: 				}
 1443: 			}
 1444: 		}
 1445: 	} else {
 1446: 		if (st & SNMP_CMD_SET) {
 1447: 			if (zend_parse_parameters(argc TSRMLS_CC, "ZZZ", &oid, &type, &value) == FAILURE) {
 1448: 				RETURN_FALSE;
 1449: 			}
 1450: 		} else if (st & SNMP_CMD_WALK) {
 1451: 			if (zend_parse_parameters(argc TSRMLS_CC, "Z|bll", &oid, &suffix_keys, &(objid_query.max_repetitions), &(objid_query.non_repeaters)) == FAILURE) {
 1452: 				RETURN_FALSE;
 1453: 			}
 1454: 			if (suffix_keys) {
 1455: 				st |= SNMP_USE_SUFFIX_AS_KEYS;
 1456: 			}
 1457: 		} else if (st & SNMP_CMD_GET) {
 1458: 			if (zend_parse_parameters(argc TSRMLS_CC, "Z|b", &oid, &use_orignames) == FAILURE) {
 1459: 				RETURN_FALSE;
 1460: 			}
 1461: 			if (use_orignames) {
 1462: 				st |= SNMP_ORIGINAL_NAMES_AS_KEYS;
 1463: 			}
 1464: 		} else {
 1465: 			/* SNMP_CMD_GETNEXT
 1466: 			 */
 1467: 			if (zend_parse_parameters(argc TSRMLS_CC, "Z", &oid) == FAILURE) {
 1468: 				RETURN_FALSE;
 1469: 			}
 1470: 		}
 1471: 	}
 1472: 
 1473: 	if (!php_snmp_parse_oid(getThis(), st, &objid_query, oid, type, value TSRMLS_CC)) {
 1474: 		RETURN_FALSE;
 1475: 	}
 1476: 
 1477: 	if (session_less_mode) {
 1478: 		if (netsnmp_session_init(&session, version, a1, a2, timeout, retries TSRMLS_CC)) {
 1479: 			efree(objid_query.vars);
 1480: 			netsnmp_session_free(&session);
 1481: 			RETURN_FALSE;
 1482: 		}
 1483: 		if (version == SNMP_VERSION_3 && netsnmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL TSRMLS_CC)) {
 1484: 			efree(objid_query.vars);
 1485: 			netsnmp_session_free(&session);
 1486: 			/* Warning message sent already, just bail out */
 1487: 			RETURN_FALSE;
 1488: 		}
 1489: 	} else {
 1490: 		zval *object = getThis();
 1491: 		snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1492: 		session = snmp_object->session;
 1493: 		if (!session) {
 1494: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or uninitialized SNMP object");
 1495: 			efree(objid_query.vars);
 1496: 			RETURN_FALSE;
 1497: 		}
 1498: 
 1499: 		if (snmp_object->max_oids > 0) {
 1500: 			objid_query.step = snmp_object->max_oids;
 1501: 			if (objid_query.max_repetitions < 0) { /* unspecified in function call, use session-wise */
 1502: 				objid_query.max_repetitions = snmp_object->max_oids;
 1503: 			}
 1504: 		}
 1505: 		objid_query.oid_increasing_check = snmp_object->oid_increasing_check;
 1506: 		objid_query.valueretrieval = snmp_object->valueretrieval;
 1507: 		glob_snmp_object.enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
 1508: 		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, snmp_object->enum_print);
 1509: 		glob_snmp_object.quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
 1510: 		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, snmp_object->quick_print);
 1511: 		glob_snmp_object.oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 1512: 		netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, snmp_object->oid_output_format);
 1513: 	}
 1514: 
 1515: 	if (objid_query.max_repetitions < 0) {
 1516: 		objid_query.max_repetitions = 20; /* provide correct default value */
 1517: 	}
 1518: 
 1519: 	php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, session, &objid_query);
 1520: 	
 1521: 	efree(objid_query.vars);
 1522: 
 1523: 	if (session_less_mode) {
 1524: 		netsnmp_session_free(&session);
 1525: 	} else {
 1526: 		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, glob_snmp_object.enum_print);
 1527: 		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, glob_snmp_object.quick_print);
 1528: 		netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, glob_snmp_object.oid_output_format);
 1529: 	}
 1530: }
 1531: /* }}} */
 1532: 
 1533: /* {{{ proto mixed snmpget(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1534:    Fetch a SNMP object */
 1535: PHP_FUNCTION(snmpget)
 1536: {
 1537: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_1);
 1538: }
 1539: /* }}} */
 1540: 
 1541: /* {{{ proto mixed snmpgetnext(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1542:    Fetch a SNMP object */
 1543: PHP_FUNCTION(snmpgetnext)
 1544: {
 1545: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_1);
 1546: }
 1547: /* }}} */
 1548: 
 1549: /* {{{ proto mixed snmpwalk(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1550:    Return all objects under the specified object id */
 1551: PHP_FUNCTION(snmpwalk)
 1552: {
 1553: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_1);
 1554: }
 1555: /* }}} */
 1556: 
 1557: /* {{{ proto mixed snmprealwalk(string host, string community, mixed object_id [, int timeout [, int retries]])
 1558:    Return all objects including their respective object id withing the specified one */
 1559: PHP_FUNCTION(snmprealwalk)
 1560: {
 1561: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_1);
 1562: }
 1563: /* }}} */
 1564: 
 1565: /* {{{ proto bool snmpset(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) 
 1566:    Set the value of a SNMP object */
 1567: PHP_FUNCTION(snmpset)
 1568: {
 1569: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_1);
 1570: }
 1571: /* }}} */
 1572: 
 1573: /* {{{ proto bool snmp_get_quick_print(void)
 1574:    Return the current status of quick_print */
 1575: PHP_FUNCTION(snmp_get_quick_print)
 1576: {
 1577: 	if (zend_parse_parameters_none() == FAILURE) {
 1578: 		return;
 1579: 	}
 1580: 
 1581: 	RETURN_BOOL(netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT));
 1582: }
 1583: /* }}} */
 1584: 
 1585: /* {{{ proto bool snmp_set_quick_print(int quick_print)
 1586:    Return all objects including their respective object id withing the specified one */
 1587: PHP_FUNCTION(snmp_set_quick_print)
 1588: {
 1589: 	long a1;
 1590: 
 1591: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 1592: 		RETURN_FALSE;
 1593: 	}
 1594: 
 1595: 	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, (int)a1);
 1596: 	RETURN_TRUE;
 1597: }
 1598: /* }}} */
 1599: 
 1600: /* {{{ proto bool snmp_set_enum_print(int enum_print)
 1601:    Return all values that are enums with their enum value instead of the raw integer */
 1602: PHP_FUNCTION(snmp_set_enum_print)
 1603: {
 1604: 	long a1;
 1605: 
 1606: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 1607: 		RETURN_FALSE;
 1608: 	}
 1609: 
 1610: 	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, (int) a1);
 1611: 	RETURN_TRUE;
 1612: } 
 1613: /* }}} */
 1614: 
 1615: /* {{{ proto bool snmp_set_oid_output_format(int oid_format)
 1616:    Set the OID output format. */
 1617: PHP_FUNCTION(snmp_set_oid_output_format)
 1618: {
 1619: 	long a1;
 1620: 
 1621: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 1622: 		RETURN_FALSE;
 1623: 	}
 1624: 
 1625: 	switch((int) a1) {
 1626: 		case NETSNMP_OID_OUTPUT_SUFFIX:
 1627: 		case NETSNMP_OID_OUTPUT_MODULE:
 1628: 		case NETSNMP_OID_OUTPUT_FULL:
 1629: 		case NETSNMP_OID_OUTPUT_NUMERIC:
 1630: 		case NETSNMP_OID_OUTPUT_UCD:
 1631: 		case NETSNMP_OID_OUTPUT_NONE:
 1632: 			netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, a1);
 1633: 			RETURN_TRUE;
 1634: 			break;
 1635: 		default:
 1636: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP output print format '%d'", (int) a1);
 1637: 			RETURN_FALSE;
 1638: 			break;
 1639: 	}
 1640: } 
 1641: /* }}} */
 1642: 
 1643: /* {{{ proto mixed snmp2_get(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1644:    Fetch a SNMP object */
 1645: PHP_FUNCTION(snmp2_get)
 1646: {
 1647: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_2c);
 1648: }
 1649: /* }}} */
 1650: 
 1651: /* {{{ proto mixed snmp2_getnext(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1652:    Fetch a SNMP object */
 1653: PHP_FUNCTION(snmp2_getnext)
 1654: {
 1655: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_2c);
 1656: }
 1657: /* }}} */
 1658: 
 1659: /* {{{ proto mixed snmp2_walk(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1660:    Return all objects under the specified object id */
 1661: PHP_FUNCTION(snmp2_walk)
 1662: {
 1663: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_2c);
 1664: }
 1665: /* }}} */
 1666: 
 1667: /* {{{ proto mixed snmp2_real_walk(string host, string community, mixed object_id [, int timeout [, int retries]])
 1668:    Return all objects including their respective object id withing the specified one */
 1669: PHP_FUNCTION(snmp2_real_walk)
 1670: {
 1671: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_2c);
 1672: }
 1673: /* }}} */
 1674: 
 1675: /* {{{ proto bool snmp2_set(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) 
 1676:    Set the value of a SNMP object */
 1677: PHP_FUNCTION(snmp2_set)
 1678: {
 1679: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_2c);
 1680: }
 1681: /* }}} */
 1682: 
 1683: /* {{{ proto mixed snmp3_get(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
 1684:    Fetch the value of a SNMP object */
 1685: PHP_FUNCTION(snmp3_get)
 1686: {
 1687: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_3);
 1688: }
 1689: /* }}} */
 1690: 
 1691: /* {{{ proto mixed snmp3_getnext(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
 1692:    Fetch the value of a SNMP object */
 1693: PHP_FUNCTION(snmp3_getnext)
 1694: {
 1695: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_3);
 1696: }
 1697: /* }}} */
 1698: 
 1699: /* {{{ proto mixed snmp3_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
 1700:    Fetch the value of a SNMP object */
 1701: PHP_FUNCTION(snmp3_walk)
 1702: {
 1703: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_3);
 1704: }
 1705: /* }}} */
 1706: 
 1707: /* {{{ proto mixed snmp3_real_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
 1708:    Fetch the value of a SNMP object */
 1709: PHP_FUNCTION(snmp3_real_walk)
 1710: {
 1711: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_3);
 1712: }
 1713: /* }}} */
 1714: 
 1715: /* {{{ proto bool snmp3_set(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id, mixed type, mixed value [, int timeout [, int retries]])
 1716:    Fetch the value of a SNMP object */
 1717: PHP_FUNCTION(snmp3_set)
 1718: {
 1719: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_3);
 1720: }
 1721: /* }}} */
 1722: 
 1723: /* {{{ proto bool snmp_set_valueretrieval(int method)
 1724:    Specify the method how the SNMP values will be returned */
 1725: PHP_FUNCTION(snmp_set_valueretrieval)
 1726: {
 1727: 	long method;
 1728: 
 1729: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
 1730: 		RETURN_FALSE;
 1731: 	}
 1732: 
 1733: 	if (method >= 0 && method <= (SNMP_VALUE_LIBRARY|SNMP_VALUE_PLAIN|SNMP_VALUE_OBJECT)) {
 1734: 			SNMP_G(valueretrieval) = method;
 1735: 			RETURN_TRUE;
 1736: 	} else {
 1737: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP value retrieval method '%ld'", method);
 1738: 		RETURN_FALSE;
 1739: 	}
 1740: }
 1741: /* }}} */
 1742: 
 1743: /* {{{ proto int snmp_get_valueretrieval()
 1744:    Return the method how the SNMP values will be returned */
 1745: PHP_FUNCTION(snmp_get_valueretrieval)
 1746: {
 1747: 	if (zend_parse_parameters_none() == FAILURE) {
 1748: 		RETURN_FALSE;
 1749: 	}
 1750: 
 1751: 	RETURN_LONG(SNMP_G(valueretrieval));
 1752: }
 1753: /* }}} */
 1754: 
 1755: /* {{{ proto bool snmp_read_mib(string filename)
 1756:    Reads and parses a MIB file into the active MIB tree. */
 1757: PHP_FUNCTION(snmp_read_mib)
 1758: {
 1759: 	char *filename;
 1760: 	int filename_len;
 1761: 
 1762: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
 1763: 		RETURN_FALSE;
 1764: 	}
 1765: 
 1766: 	if (!read_mib(filename)) {
 1767: 		char *error = strerror(errno);
 1768: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading MIB file '%s': %s", filename, error);
 1769: 		RETURN_FALSE;
 1770: 	}
 1771: 	RETURN_TRUE;
 1772: }
 1773: /* }}} */
 1774: 
 1775: /* {{{ proto SNMP SNMP::__construct(int version, string hostname, string community|securityName [, long timeout [, long retries]])
 1776: 	Creates a new SNMP session to specified host. */
 1777: PHP_METHOD(snmp, __construct)
 1778: {
 1779: 	php_snmp_object *snmp_object;
 1780: 	zval *object = getThis();
 1781: 	char *a1, *a2;
 1782: 	int a1_len, a2_len;
 1783: 	long timeout = SNMP_DEFAULT_TIMEOUT;
 1784: 	long retries = SNMP_DEFAULT_RETRIES;
 1785: 	long version = SNMP_DEFAULT_VERSION;
 1786: 	int argc = ZEND_NUM_ARGS();
 1787: 	zend_error_handling error_handling;
 1788: 
 1789: 	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1790: 	zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
 1791: 	
 1792: 	if (zend_parse_parameters(argc TSRMLS_CC, "lss|ll", &version, &a1, &a1_len, &a2, &a2_len, &timeout, &retries) == FAILURE) {
 1793: 		zend_restore_error_handling(&error_handling TSRMLS_CC);
 1794: 		return;
 1795: 	}
 1796: 
 1797: 	zend_restore_error_handling(&error_handling TSRMLS_CC);
 1798: 
 1799: 	switch(version) {
 1800: 		case SNMP_VERSION_1:
 1801: 		case SNMP_VERSION_2c:
 1802: 		case SNMP_VERSION_3:
 1803: 			break;
 1804: 		default:
 1805: 			zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Unknown SNMP protocol version", 0 TSRMLS_CC);
 1806: 			return;
 1807: 	}
 1808: 
 1809: 	/* handle re-open of snmp session */
 1810: 	if (snmp_object->session) {
 1811: 		netsnmp_session_free(&(snmp_object->session));
 1812: 	}
 1813: 	
 1814: 	if (netsnmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries TSRMLS_CC)) {
 1815: 		return;
 1816: 	}
 1817: 	snmp_object->max_oids = 0;
 1818: 	snmp_object->valueretrieval = SNMP_G(valueretrieval);
 1819: 	snmp_object->enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
 1820: 	snmp_object->oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 1821: 	snmp_object->quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
 1822: 	snmp_object->oid_increasing_check = TRUE;
 1823: 	snmp_object->exceptions_enabled = 0;
 1824: }
 1825: /* }}} */
 1826: 
 1827: /* {{{ proto bool SNMP::close() 
 1828: 	Close SNMP session */
 1829: PHP_METHOD(snmp, close)
 1830: {
 1831: 	php_snmp_object *snmp_object;
 1832: 	zval *object = getThis();
 1833: 
 1834: 	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1835: 
 1836: 	if (zend_parse_parameters_none() == FAILURE) {
 1837: 		RETURN_FALSE;
 1838: 	}
 1839: 
 1840: 	netsnmp_session_free(&(snmp_object->session));
 1841: 
 1842: 	RETURN_TRUE;
 1843: }
 1844: /* }}} */
 1845: 
 1846: /* {{{ proto mixed SNMP::get(mixed object_id [, bool preserve_keys])
 1847:    Fetch a SNMP object returing scalar for single OID and array of oid->value pairs for multi OID request */
 1848: PHP_METHOD(snmp, get)
 1849: {
 1850: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, (-1));
 1851: }
 1852: /* }}} */
 1853: 
 1854: /* {{{ proto mixed SNMP::getnext(mixed object_id)
 1855:    Fetch a SNMP object returing scalar for single OID and array of oid->value pairs for multi OID request */
 1856: PHP_METHOD(snmp, getnext)
 1857: {
 1858: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, (-1));
 1859: }
 1860: /* }}} */
 1861: 
 1862: /* {{{ proto mixed SNMP::walk(mixed object_id [, bool $suffix_as_key = FALSE [, int $max_repetitions [, int $non_repeaters]])
 1863:    Return all objects including their respective object id withing the specified one as array of oid->value pairs */
 1864: PHP_METHOD(snmp, walk)
 1865: {
 1866: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, (-1));
 1867: }
 1868: /* }}} */
 1869: 
 1870: /* {{{ proto bool SNMP::set(mixed object_id, mixed type, mixed value) 
 1871:    Set the value of a SNMP object */
 1872: PHP_METHOD(snmp, set)
 1873: {
 1874: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, (-1));
 1875: }
 1876: 
 1877: /* {{{ proto bool SNMP::setSecurity(string sec_level, [ string auth_protocol, string auth_passphrase [, string priv_protocol, string priv_passphrase [, string contextName [, string contextEngineID]]]])
 1878: 	Set SNMPv3 security-related session parameters */
 1879: PHP_METHOD(snmp, setSecurity)
 1880: {
 1881: 	php_snmp_object *snmp_object;
 1882: 	zval *object = getThis();
 1883: 	char *a1 = "", *a2 = "", *a3 = "", *a4 = "", *a5 = "", *a6 = "", *a7 = "";
 1884: 	int a1_len = 0, a2_len = 0, a3_len = 0, a4_len = 0, a5_len = 0, a6_len = 0, a7_len = 0;
 1885: 	int argc = ZEND_NUM_ARGS();
 1886: 
 1887: 	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1888: 	
 1889: 	if (zend_parse_parameters(argc TSRMLS_CC, "s|ssssss", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 1890: 		&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len) == FAILURE) {
 1891: 		RETURN_FALSE;
 1892: 	}
 1893: 
 1894: 	if (netsnmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7 TSRMLS_CC)) {
 1895: 		/* Warning message sent already, just bail out */
 1896: 		RETURN_FALSE;
 1897: 	}
 1898: 	RETURN_TRUE;
 1899: }
 1900: /* }}} */
 1901: 
 1902: /* {{{ proto long SNMP::getErrno() 
 1903: 	Get last error code number */
 1904: PHP_METHOD(snmp, getErrno)
 1905: {
 1906: 	php_snmp_object *snmp_object;
 1907: 	zval *object = getThis();
 1908: 
 1909: 	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1910: 
 1911: 	RETVAL_LONG(snmp_object->snmp_errno);
 1912: 	return;
 1913: }
 1914: /* }}} */
 1915: 
 1916: /* {{{ proto long SNMP::getError() 
 1917: 	Get last error message */
 1918: PHP_METHOD(snmp, getError)
 1919: {
 1920: 	php_snmp_object *snmp_object;
 1921: 	zval *object = getThis();
 1922: 
 1923: 	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1924: 
 1925: 	RETVAL_STRING(snmp_object->snmp_errstr, 1);
 1926: 	return;
 1927: }
 1928: /* }}} */
 1929: 
 1930: /* {{{ */
 1931: void php_snmp_add_property(HashTable *h, const char *name, size_t name_length, php_snmp_read_t read_func, php_snmp_write_t write_func TSRMLS_DC)
 1932: {
 1933: 	php_snmp_prop_handler p;
 1934: 
 1935: 	p.name = (char*) name;
 1936: 	p.name_length = name_length;
 1937: 	p.read_func = (read_func) ? read_func : NULL;
 1938: 	p.write_func = (write_func) ? write_func : NULL;
 1939: 	zend_hash_add(h, (char *)name, name_length + 1, &p, sizeof(php_snmp_prop_handler), NULL);
 1940: }
 1941: /* }}} */
 1942: 
 1943: /* {{{ php_snmp_read_property(zval *object, zval *member, int type[, const zend_literal *key])
 1944:    Generic object property reader */
 1945: zval *php_snmp_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
 1946: {
 1947: 	zval tmp_member;
 1948: 	zval *retval;
 1949: 	php_snmp_object *obj;
 1950: 	php_snmp_prop_handler *hnd;
 1951: 	int ret;
 1952: 
 1953: 	ret = FAILURE;
 1954: 	obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
 1955: 
 1956: 	if (Z_TYPE_P(member) != IS_STRING) {
 1957: 		tmp_member = *member;
 1958: 		zval_copy_ctor(&tmp_member);
 1959: 		convert_to_string(&tmp_member);
 1960: 		member = &tmp_member;
 1961: 	}
 1962: 
 1963: 	ret = zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
 1964: 
 1965: 	if (ret == SUCCESS && hnd->read_func) {
 1966: 		ret = hnd->read_func(obj, &retval TSRMLS_CC);
 1967: 		if (ret == SUCCESS) {
 1968: 			/* ensure we're creating a temporary variable */
 1969: 			Z_SET_REFCOUNT_P(retval, 0);
 1970: 		} else {
 1971: 			retval = EG(uninitialized_zval_ptr);
 1972: 		}
 1973: 	} else {
 1974: 		zend_object_handlers * std_hnd = zend_get_std_object_handlers();
 1975: 		retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
 1976: 	}
 1977: 
 1978: 	if (member == &tmp_member) {
 1979: 		zval_dtor(member);
 1980: 	}
 1981: 	return(retval);
 1982: }
 1983: /* }}} */
 1984: 
 1985: /* {{{ php_snmp_write_property(zval *object, zval *member, zval *value[, const zend_literal *key])
 1986:    Generic object property writer */
 1987: void php_snmp_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
 1988: {
 1989: 	zval tmp_member;
 1990: 	php_snmp_object *obj;
 1991: 	php_snmp_prop_handler *hnd;
 1992: 	int ret;
 1993: 
 1994: 	if (Z_TYPE_P(member) != IS_STRING) {
 1995: 		tmp_member = *member;
 1996: 		zval_copy_ctor(&tmp_member);
 1997: 		convert_to_string(&tmp_member);
 1998: 		member = &tmp_member;
 1999: 	}
 2000: 
 2001: 	ret = FAILURE;
 2002: 	obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
 2003: 
 2004: 	ret = zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **) &hnd);
 2005: 
 2006: 	if (ret == SUCCESS && hnd->write_func) {
 2007: 		hnd->write_func(obj, value TSRMLS_CC);
 2008: 		if (! PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) == 0) {
 2009: 			Z_ADDREF_P(value);
 2010: 			zval_ptr_dtor(&value);
 2011: 		}
 2012: 	} else {
 2013: 		zend_object_handlers * std_hnd = zend_get_std_object_handlers();
 2014: 		std_hnd->write_property(object, member, value, key TSRMLS_CC);
 2015: 	}
 2016: 
 2017: 	if (member == &tmp_member) {
 2018: 		zval_dtor(member);
 2019: 	}
 2020: }
 2021: /* }}} */
 2022: 
 2023: /* {{{ php_snmp_has_property(zval *object, zval *member, int has_set_exists[, const zend_literal *key])
 2024:    Generic object property checker */
 2025: static int php_snmp_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC)
 2026: {
 2027: 	php_snmp_prop_handler *hnd;
 2028: 	int ret = 0;
 2029: 
 2030: 	if (zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **)&hnd) == SUCCESS) {
 2031: 		switch (has_set_exists) {
 2032: 			case 2:
 2033: 				ret = 1;
 2034: 				break;
 2035: 			case 0: {
 2036: 				zval *value = php_snmp_read_property(object, member, BP_VAR_IS, key TSRMLS_CC);
 2037: 				if (value != EG(uninitialized_zval_ptr)) {
 2038: 					ret = Z_TYPE_P(value) != IS_NULL? 1:0;
 2039: 					/* refcount is 0 */
 2040: 					Z_ADDREF_P(value);
 2041: 					zval_ptr_dtor(&value);
 2042: 				}
 2043: 				break;
 2044: 			}
 2045: 			default: {
 2046: 				zval *value = php_snmp_read_property(object, member, BP_VAR_IS, key TSRMLS_CC);
 2047: 				if (value != EG(uninitialized_zval_ptr)) {
 2048: 					convert_to_boolean(value);
 2049: 					ret = Z_BVAL_P(value)? 1:0;
 2050: 					/* refcount is 0 */
 2051: 					Z_ADDREF_P(value);
 2052: 					zval_ptr_dtor(&value);
 2053: 				}
 2054: 				break;
 2055: 			}
 2056: 		}
 2057: 	} else {
 2058: 		zend_object_handlers * std_hnd = zend_get_std_object_handlers();
 2059: 		ret = std_hnd->has_property(object, member, has_set_exists, key TSRMLS_CC);
 2060: 	}
 2061: 	return ret;
 2062: }
 2063: /* }}} */
 2064: 
 2065: /* {{{ php_snmp_get_properties(zval *object)
 2066:    Returns all object properties. Injects SNMP properties into object on first call */
 2067: static HashTable *php_snmp_get_properties(zval *object TSRMLS_DC)
 2068: {
 2069: 	php_snmp_object *obj;
 2070: 	php_snmp_prop_handler *hnd;
 2071: 	HashTable *props;
 2072: 	zval *val;
 2073: 	char *key;
 2074: 	uint key_len;
 2075: 	HashPosition pos;
 2076: 	ulong num_key;
 2077: 
 2078: 	obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
 2079: 	props = zend_std_get_properties(object TSRMLS_CC);
 2080: 
 2081: 	zend_hash_internal_pointer_reset_ex(&php_snmp_properties, &pos);
 2082: 
 2083: 	while (zend_hash_get_current_data_ex(&php_snmp_properties, (void**)&hnd, &pos) == SUCCESS) {
 2084: 		zend_hash_get_current_key_ex(&php_snmp_properties, &key, &key_len, &num_key, 0, &pos);
 2085: 		if (!hnd->read_func || hnd->read_func(obj, &val TSRMLS_CC) != SUCCESS) {
 2086: 			val = EG(uninitialized_zval_ptr);
 2087: 			Z_ADDREF_P(val);
 2088: 		}
 2089: 		zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
 2090: 		zend_hash_move_forward_ex(&php_snmp_properties, &pos);
 2091: 	}
 2092: 	return obj->zo.properties;
 2093: }
 2094: /* }}} */
 2095: 
 2096: /* {{{ */
 2097: static int php_snmp_read_info(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
 2098: {
 2099: 	zval *val;
 2100: 
 2101: 	MAKE_STD_ZVAL(*retval);
 2102: 	array_init(*retval);
 2103: 
 2104: 	if (snmp_object->session == NULL) {
 2105: 		return SUCCESS;
 2106: 	}
 2107: 		
 2108: 	MAKE_STD_ZVAL(val);
 2109: 	ZVAL_STRINGL(val, snmp_object->session->peername, strlen(snmp_object->session->peername), 1);
 2110: 	add_assoc_zval(*retval, "hostname", val);
 2111: 	
 2112: 	MAKE_STD_ZVAL(val);
 2113: 	ZVAL_LONG(val, snmp_object->session->remote_port);
 2114: 	add_assoc_zval(*retval, "port", val);
 2115: 	
 2116: 	MAKE_STD_ZVAL(val);
 2117: 	ZVAL_LONG(val, snmp_object->session->timeout);
 2118: 	add_assoc_zval(*retval, "timeout", val);
 2119: 	
 2120: 	MAKE_STD_ZVAL(val);
 2121: 	ZVAL_LONG(val, snmp_object->session->retries);
 2122: 	add_assoc_zval(*retval, "retries", val);
 2123: 	
 2124: 	return SUCCESS;
 2125: }
 2126: /* }}} */
 2127: 
 2128: /* {{{ */
 2129: static int php_snmp_read_max_oids(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
 2130: {
 2131: 	MAKE_STD_ZVAL(*retval);
 2132: 	if (snmp_object->max_oids > 0) {
 2133: 		ZVAL_LONG(*retval, snmp_object->max_oids);
 2134: 	} else {
 2135: 		ZVAL_NULL(*retval);
 2136: 	}
 2137: 	return SUCCESS;
 2138: }
 2139: /* }}} */
 2140: 
 2141: #define PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(name) \
 2142: 	static int php_snmp_read_##name(php_snmp_object *snmp_object, zval **retval TSRMLS_DC) \
 2143: 	{ \
 2144: 		MAKE_STD_ZVAL(*retval); \
 2145: 		ZVAL_BOOL(*retval, snmp_object->name); \
 2146: 		return SUCCESS; \
 2147: 	}
 2148: 
 2149: PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(oid_increasing_check)
 2150: PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(quick_print)
 2151: PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(enum_print)
 2152: 
 2153: #define PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(name) \
 2154: 	static int php_snmp_read_##name(php_snmp_object *snmp_object, zval **retval TSRMLS_DC) \
 2155: 	{ \
 2156: 		MAKE_STD_ZVAL(*retval); \
 2157: 		ZVAL_LONG(*retval, snmp_object->name); \
 2158: 		return SUCCESS; \
 2159: 	}
 2160: 
 2161: PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(valueretrieval)
 2162: PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(oid_output_format)
 2163: PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(exceptions_enabled)
 2164: 
 2165: /* {{{ */
 2166: static int php_snmp_write_info(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 2167: {
 2168: 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "info property is read-only");
 2169: 	return FAILURE;
 2170: }
 2171: /* }}} */
 2172: 
 2173: /* {{{ */
 2174: static int php_snmp_write_max_oids(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 2175: {
 2176: 	zval ztmp;
 2177: 	int ret = SUCCESS;
 2178: 
 2179: 	if (Z_TYPE_P(newval) == IS_NULL) {
 2180: 		snmp_object->max_oids = 0;
 2181: 		return ret;
 2182: 	}
 2183: 
 2184: 	if (Z_TYPE_P(newval) != IS_LONG) {
 2185: 		ztmp = *newval;
 2186: 		zval_copy_ctor(&ztmp);
 2187: 		convert_to_long(&ztmp);
 2188: 		newval = &ztmp;
 2189: 	}
 2190: 
 2191: 	if (Z_LVAL_P(newval) > 0) {
 2192: 		snmp_object->max_oids = Z_LVAL_P(newval);
 2193: 	} else {
 2194: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "max_oids should be positive integer or NULL, got %ld", Z_LVAL_P(newval));
 2195: 	}
 2196: 	
 2197: 	if (newval == &ztmp) {
 2198: 		zval_dtor(newval);
 2199: 	}
 2200: 
 2201: 	return ret;
 2202: }
 2203: /* }}} */
 2204: 
 2205: /* {{{ */
 2206: static int php_snmp_write_valueretrieval(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 2207: {
 2208: 	zval ztmp;
 2209: 	int ret = SUCCESS;
 2210: 
 2211: 	if (Z_TYPE_P(newval) != IS_LONG) {
 2212: 		ztmp = *newval;
 2213: 		zval_copy_ctor(&ztmp);
 2214: 		convert_to_long(&ztmp);
 2215: 		newval = &ztmp;
 2216: 	}
 2217: 
 2218: 	if (Z_LVAL_P(newval) >= 0 && Z_LVAL_P(newval) <= (SNMP_VALUE_LIBRARY|SNMP_VALUE_PLAIN|SNMP_VALUE_OBJECT)) {
 2219: 		snmp_object->valueretrieval = Z_LVAL_P(newval);
 2220: 	} else {
 2221: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP value retrieval method '%ld'", Z_LVAL_P(newval));
 2222: 		ret = FAILURE;
 2223: 	}
 2224: 	
 2225: 	if (newval == &ztmp) {
 2226: 		zval_dtor(newval);
 2227: 	}
 2228: 
 2229: 	return ret;
 2230: }
 2231: /* }}} */
 2232: 
 2233: #define PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(name) \
 2234: static int php_snmp_write_##name(php_snmp_object *snmp_object, zval *newval TSRMLS_DC) \
 2235: { \
 2236: 	zval ztmp; \
 2237: 	if (Z_TYPE_P(newval) != IS_BOOL) { \
 2238: 		ztmp = *newval; \
 2239: 		zval_copy_ctor(&ztmp); \
 2240: 		convert_to_boolean(&ztmp); \
 2241: 		newval = &ztmp; \
 2242: 	} \
 2243: \
 2244: 	snmp_object->name = Z_LVAL_P(newval); \
 2245: \
 2246: 	if (newval == &ztmp) { \
 2247: 		zval_dtor(newval); \
 2248: 	} \
 2249: 	return SUCCESS; \
 2250: }
 2251: 
 2252: PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(quick_print)
 2253: PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(enum_print)
 2254: PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(oid_increasing_check)
 2255: 
 2256: /* {{{ */
 2257: static int php_snmp_write_oid_output_format(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 2258: {
 2259: 	zval ztmp;
 2260: 	int ret = SUCCESS;
 2261: 	if (Z_TYPE_P(newval) != IS_LONG) {
 2262: 		ztmp = *newval;
 2263: 		zval_copy_ctor(&ztmp);
 2264: 		convert_to_long(&ztmp);
 2265: 		newval = &ztmp;
 2266: 	}
 2267: 	
 2268: 	switch(Z_LVAL_P(newval)) {
 2269: 		case NETSNMP_OID_OUTPUT_SUFFIX:
 2270: 		case NETSNMP_OID_OUTPUT_MODULE:
 2271: 		case NETSNMP_OID_OUTPUT_FULL:
 2272: 		case NETSNMP_OID_OUTPUT_NUMERIC:
 2273: 		case NETSNMP_OID_OUTPUT_UCD:
 2274: 		case NETSNMP_OID_OUTPUT_NONE:
 2275: 			snmp_object->oid_output_format = Z_LVAL_P(newval);
 2276: 			break;
 2277: 		default:
 2278: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP output print format '%ld'", Z_LVAL_P(newval));
 2279: 			ret = FAILURE;
 2280: 			break;
 2281: 	}
 2282: 
 2283: 	if (newval == &ztmp) {
 2284: 		zval_dtor(newval);
 2285: 	}
 2286: 	return ret;
 2287: }
 2288: /* }}} */
 2289: 
 2290: /* {{{ */
 2291: static int php_snmp_write_exceptions_enabled(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 2292: {
 2293: 	zval ztmp;
 2294: 	int ret = SUCCESS;
 2295: 	if (Z_TYPE_P(newval) != IS_LONG) {
 2296: 		ztmp = *newval;
 2297: 		zval_copy_ctor(&ztmp);
 2298: 		convert_to_long(&ztmp);
 2299: 		newval = &ztmp;
 2300: 	}
 2301: 
 2302: 	snmp_object->exceptions_enabled = Z_LVAL_P(newval);	
 2303: 
 2304: 	if (newval == &ztmp) {
 2305: 		zval_dtor(newval);
 2306: 	}
 2307: 	return ret;
 2308: }
 2309: /* }}} */
 2310: 
 2311: /* {{{ php_snmp_class_methods[] */
 2312: static zend_function_entry php_snmp_class_methods[] = {
 2313: 	PHP_ME(snmp,	 __construct,			arginfo_snmp_create,		ZEND_ACC_PUBLIC)
 2314: 	PHP_ME(snmp,	 close,				arginfo_snmp_void,		ZEND_ACC_PUBLIC)
 2315: 	PHP_ME(snmp,	 setSecurity,			arginfo_snmp_setSecurity,	ZEND_ACC_PUBLIC)
 2316: 
 2317: 	PHP_ME(snmp,	 get,				arginfo_snmp_get,		ZEND_ACC_PUBLIC)
 2318: 	PHP_ME(snmp,	 getnext,			arginfo_snmp_get,		ZEND_ACC_PUBLIC)
 2319: 	PHP_ME(snmp,	 walk,				arginfo_snmp_walk,		ZEND_ACC_PUBLIC)
 2320: 	PHP_ME(snmp,	 set,				arginfo_snmp_set,		ZEND_ACC_PUBLIC)
 2321: 	PHP_ME(snmp,	 getErrno,			arginfo_snmp_void,		ZEND_ACC_PUBLIC)
 2322: 	PHP_ME(snmp,	 getError,			arginfo_snmp_void,		ZEND_ACC_PUBLIC)
 2323: 
 2324: 	PHP_FE_END
 2325: };
 2326: 
 2327: #define PHP_SNMP_PROPERTY_ENTRY_RECORD(name) \
 2328: 	{ "" #name "",		sizeof("" #name "") - 1,	php_snmp_read_##name,	php_snmp_write_##name }
 2329: 
 2330: const php_snmp_prop_handler php_snmp_property_entries[] = {
 2331: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(info),
 2332: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(max_oids),
 2333: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(valueretrieval),
 2334: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(quick_print),
 2335: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(enum_print),
 2336: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(oid_output_format),
 2337: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(oid_increasing_check),
 2338: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(exceptions_enabled),
 2339: 	{ NULL, 0, NULL, NULL}
 2340: };
 2341: /* }}} */
 2342: 
 2343: /* {{{ PHP_MINIT_FUNCTION
 2344:  */
 2345: PHP_MINIT_FUNCTION(snmp)
 2346: {
 2347: 	netsnmp_log_handler *logh;
 2348: 	zend_class_entry ce, cex;
 2349: 
 2350: 	le_snmp_session = zend_register_list_destructors_ex(php_snmp_session_destructor, NULL, PHP_SNMP_SESSION_RES_NAME, module_number);
 2351: 
 2352: 	init_snmp("snmpapp");
 2353: 
 2354: #ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
 2355: 	/* Prevent update of the snmpapp.conf file */
 2356: 	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
 2357: #endif
 2358: 
 2359: 	/* Disable logging, use exit status'es and related variabled to detect errors */
 2360: 	shutdown_snmp_logging();
 2361: 	logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_NONE, LOG_ERR);
 2362: 	if (logh) {
 2363: 		logh->pri_max = LOG_ERR;
 2364: 	}
 2365: 
 2366: 	memcpy(&php_snmp_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
 2367: 	php_snmp_object_handlers.read_property = php_snmp_read_property;
 2368: 	php_snmp_object_handlers.write_property = php_snmp_write_property;
 2369: 	php_snmp_object_handlers.has_property = php_snmp_has_property;
 2370: 	php_snmp_object_handlers.get_properties = php_snmp_get_properties;
 2371: 
 2372: 	/* Register SNMP Class */
 2373: 	INIT_CLASS_ENTRY(ce, "SNMP", php_snmp_class_methods);
 2374: 	ce.create_object = php_snmp_object_new;
 2375: 	php_snmp_object_handlers.clone_obj = NULL;
 2376: 	php_snmp_ce = zend_register_internal_class(&ce TSRMLS_CC);
 2377: 
 2378: 	/* Register SNMP Class properties */
 2379: 	zend_hash_init(&php_snmp_properties, 0, NULL, NULL, 1);
 2380: 	PHP_SNMP_ADD_PROPERTIES(&php_snmp_properties, php_snmp_property_entries);
 2381: 
 2382: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_SUFFIX",	NETSNMP_OID_OUTPUT_SUFFIX,	CONST_CS | CONST_PERSISTENT);
 2383: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_MODULE",	NETSNMP_OID_OUTPUT_MODULE,	CONST_CS | CONST_PERSISTENT);
 2384: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_FULL",		NETSNMP_OID_OUTPUT_FULL,	CONST_CS | CONST_PERSISTENT);
 2385: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NUMERIC",	NETSNMP_OID_OUTPUT_NUMERIC,	CONST_CS | CONST_PERSISTENT);
 2386: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_UCD",		NETSNMP_OID_OUTPUT_UCD,		CONST_CS | CONST_PERSISTENT);
 2387: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NONE",		NETSNMP_OID_OUTPUT_NONE,	CONST_CS | CONST_PERSISTENT);
 2388: 
 2389: 	REGISTER_LONG_CONSTANT("SNMP_VALUE_LIBRARY",	SNMP_VALUE_LIBRARY,	CONST_CS | CONST_PERSISTENT);
 2390: 	REGISTER_LONG_CONSTANT("SNMP_VALUE_PLAIN",	SNMP_VALUE_PLAIN,	CONST_CS | CONST_PERSISTENT);
 2391: 	REGISTER_LONG_CONSTANT("SNMP_VALUE_OBJECT",	SNMP_VALUE_OBJECT,	CONST_CS | CONST_PERSISTENT);
 2392: 
 2393: 	REGISTER_LONG_CONSTANT("SNMP_BIT_STR",		ASN_BIT_STR,	CONST_CS | CONST_PERSISTENT);
 2394: 	REGISTER_LONG_CONSTANT("SNMP_OCTET_STR",	ASN_OCTET_STR,	CONST_CS | CONST_PERSISTENT);
 2395: 	REGISTER_LONG_CONSTANT("SNMP_OPAQUE",		ASN_OPAQUE,	CONST_CS | CONST_PERSISTENT);
 2396: 	REGISTER_LONG_CONSTANT("SNMP_NULL",		ASN_NULL,	CONST_CS | CONST_PERSISTENT);
 2397: 	REGISTER_LONG_CONSTANT("SNMP_OBJECT_ID",	ASN_OBJECT_ID,	CONST_CS | CONST_PERSISTENT);
 2398: 	REGISTER_LONG_CONSTANT("SNMP_IPADDRESS",	ASN_IPADDRESS,	CONST_CS | CONST_PERSISTENT);
 2399: 	REGISTER_LONG_CONSTANT("SNMP_COUNTER",		ASN_GAUGE,	CONST_CS | CONST_PERSISTENT);
 2400: 	REGISTER_LONG_CONSTANT("SNMP_UNSIGNED",		ASN_UNSIGNED,	CONST_CS | CONST_PERSISTENT);
 2401: 	REGISTER_LONG_CONSTANT("SNMP_TIMETICKS",	ASN_TIMETICKS,	CONST_CS | CONST_PERSISTENT);
 2402: 	REGISTER_LONG_CONSTANT("SNMP_UINTEGER",		ASN_UINTEGER,	CONST_CS | CONST_PERSISTENT);
 2403: 	REGISTER_LONG_CONSTANT("SNMP_INTEGER",		ASN_INTEGER,	CONST_CS | CONST_PERSISTENT);
 2404: 	REGISTER_LONG_CONSTANT("SNMP_COUNTER64",	ASN_COUNTER64,	CONST_CS | CONST_PERSISTENT);
 2405: 
 2406: 	REGISTER_SNMP_CLASS_CONST_LONG("VERSION_1",			SNMP_VERSION_1);
 2407: 	REGISTER_SNMP_CLASS_CONST_LONG("VERSION_2c",			SNMP_VERSION_2c);
 2408: 	REGISTER_SNMP_CLASS_CONST_LONG("VERSION_2C",			SNMP_VERSION_2c);
 2409: 	REGISTER_SNMP_CLASS_CONST_LONG("VERSION_3",			SNMP_VERSION_3);
 2410: 
 2411: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_NOERROR",			PHP_SNMP_ERRNO_NOERROR);
 2412: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_ANY",			PHP_SNMP_ERRNO_ANY);
 2413: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_GENERIC",			PHP_SNMP_ERRNO_GENERIC);
 2414: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_TIMEOUT",			PHP_SNMP_ERRNO_TIMEOUT);
 2415: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_ERROR_IN_REPLY",		PHP_SNMP_ERRNO_ERROR_IN_REPLY);
 2416: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_OID_NOT_INCREASING",	PHP_SNMP_ERRNO_OID_NOT_INCREASING);
 2417: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_OID_PARSING_ERROR",	PHP_SNMP_ERRNO_OID_PARSING_ERROR);
 2418: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_MULTIPLE_SET_QUERIES",	PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES);
 2419: 
 2420: 	/* Register SNMPException class */
 2421: 	INIT_CLASS_ENTRY(cex, "SNMPException", NULL);
 2422: #ifdef HAVE_SPL
 2423: 	php_snmp_exception_ce = zend_register_internal_class_ex(&cex, spl_ce_RuntimeException, NULL TSRMLS_CC);
 2424: #else
 2425: 	php_snmp_exception_ce = zend_register_internal_class_ex(&cex, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
 2426: #endif
 2427: 
 2428: 	return SUCCESS;
 2429: }
 2430: /* }}} */
 2431: 
 2432: /* {{{ PHP_MSHUTDOWN_FUNCTION
 2433:  */
 2434: PHP_MSHUTDOWN_FUNCTION(snmp)
 2435: {
 2436: 	snmp_shutdown("snmpapp");
 2437: 	
 2438: 	zend_hash_destroy(&php_snmp_properties);
 2439: 
 2440: 	return SUCCESS;
 2441: }
 2442: /* }}} */
 2443: 
 2444: /* {{{ PHP_MINFO_FUNCTION
 2445:  */
 2446: PHP_MINFO_FUNCTION(snmp)
 2447: {
 2448: 	php_info_print_table_start();
 2449: 	php_info_print_table_row(2, "NET-SNMP Support", "enabled");
 2450: 	php_info_print_table_row(2, "NET-SNMP Version", netsnmp_get_version());
 2451: 	php_info_print_table_row(2, "PHP SNMP Version", PHP_SNMP_VERSION);
 2452: 	php_info_print_table_end();
 2453: }
 2454: /* }}} */
 2455: 
 2456: /* {{{ snmp_module_deps[]
 2457:  */
 2458: static const zend_module_dep snmp_module_deps[] = {
 2459: #ifdef HAVE_SPL
 2460: 	ZEND_MOD_REQUIRED("spl")
 2461: #endif
 2462: 	ZEND_MOD_END
 2463: };
 2464: /* }}} */
 2465: 
 2466: /* {{{ snmp_module_entry
 2467:  */
 2468: zend_module_entry snmp_module_entry = {
 2469: 	STANDARD_MODULE_HEADER_EX,
 2470: 	NULL,
 2471: 	snmp_module_deps,
 2472: 	"snmp",
 2473: 	snmp_functions,
 2474: 	PHP_MINIT(snmp),
 2475: 	PHP_MSHUTDOWN(snmp),
 2476: 	NULL,
 2477: 	NULL,
 2478: 	PHP_MINFO(snmp),
 2479: 	PHP_SNMP_VERSION,
 2480: 	PHP_MODULE_GLOBALS(snmp),
 2481: 	PHP_GINIT(snmp),
 2482: 	NULL,
 2483: 	NULL,
 2484: 	STANDARD_MODULE_PROPERTIES_EX
 2485: };
 2486: /* }}} */
 2487: 
 2488: #endif
 2489: 
 2490: /*
 2491:  * Local variables:
 2492:  * tab-width: 4
 2493:  * c-basic-offset: 4
 2494:  * End:
 2495:  * vim600: sw=4 ts=4 fdm=marker
 2496:  * vim<600: sw=4 ts=4
 2497:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>