File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / snmp / snmp.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:55 2014 UTC (10 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2014 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.5 2014/06/15 20:03:55 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 = NULL;
  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 TSRMLS_CC, snmp_object->snmp_errstr);
  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: 	char sbuf[512];
  555: 	char *buf = &(sbuf[0]);
  556: 	char *dbuf = (char *)NULL;
  557: 	int buflen = sizeof(sbuf) - 1;
  558: 	int val_len = vars->val_len;
  559: 	
  560: 	/* use emalloc() for large values, use static array otherwize */
  561: 
  562: 	/* There is no way to know the size of buffer snprint_value() needs in order to print a value there.
  563: 	 * So we are forced to probe it
  564: 	 */
  565: 	while ((valueretrieval & SNMP_VALUE_PLAIN) == 0) {
  566: 		*buf = '\0';
  567: 		if (snprint_value(buf, buflen, vars->name, vars->name_length, vars) == -1) {
  568: 			if (val_len > 512*1024) {
  569: 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "snprint_value() asks for a buffer more than 512k, Net-SNMP bug?");
  570: 				break;
  571: 			}
  572: 			 /* buffer is not long enough to hold full output, double it */
  573: 			val_len *= 2;
  574: 		} else {
  575: 			break;
  576: 		}
  577: 
  578: 		if (buf == dbuf) {
  579: 			dbuf = (char *)erealloc(dbuf, val_len + 1);
  580: 		} else {
  581: 			dbuf = (char *)emalloc(val_len + 1);
  582: 		}
  583: 
  584: 		if (!dbuf) {
  585: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed: %s, fallback to static buffer", strerror(errno));
  586: 			buf = &(sbuf[0]);
  587: 			buflen = sizeof(sbuf) - 1;
  588: 			break;
  589: 		}
  590: 
  591: 		buf = dbuf;
  592: 		buflen = val_len;
  593: 	}
  594: 
  595: 	if((valueretrieval & SNMP_VALUE_PLAIN) && val_len > buflen){
  596: 		if ((dbuf = (char *)emalloc(val_len + 1))) {
  597: 			buf = dbuf;
  598: 			buflen = val_len;
  599: 		} else {
  600: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed: %s, fallback to static buffer", strerror(errno));
  601: 		}
  602: 	}
  603: 
  604: 	MAKE_STD_ZVAL(val);
  605: 
  606: 	if (valueretrieval & SNMP_VALUE_PLAIN) {
  607: 		*buf = 0;
  608: 		switch (vars->type) {
  609: 		case ASN_BIT_STR:		/* 0x03, asn1.h */
  610: 			ZVAL_STRINGL(val, (char *)vars->val.bitstring, vars->val_len, 1);
  611: 			break;
  612: 
  613: 		case ASN_OCTET_STR:		/* 0x04, asn1.h */
  614: 		case ASN_OPAQUE:		/* 0x44, snmp_impl.h */
  615: 			ZVAL_STRINGL(val, (char *)vars->val.string, vars->val_len, 1);
  616: 			break;
  617: 
  618: 		case ASN_NULL:			/* 0x05, asn1.h */
  619: 			ZVAL_NULL(val);
  620: 			break;
  621: 
  622: 		case ASN_OBJECT_ID:		/* 0x06, asn1.h */
  623: 			snprint_objid(buf, buflen, vars->val.objid, vars->val_len / sizeof(oid));
  624: 			ZVAL_STRING(val, buf, 1);
  625: 			break;
  626: 
  627: 		case ASN_IPADDRESS:		/* 0x40, snmp_impl.h */
  628: 			snprintf(buf, buflen, "%d.%d.%d.%d",
  629: 				 (vars->val.string)[0], (vars->val.string)[1],
  630: 				 (vars->val.string)[2], (vars->val.string)[3]);
  631: 			buf[buflen]=0;
  632: 			ZVAL_STRING(val, buf, 1);
  633: 			break;
  634: 
  635: 		case ASN_COUNTER:		/* 0x41, snmp_impl.h */
  636: 		case ASN_GAUGE:			/* 0x42, snmp_impl.h */
  637: 		/* ASN_UNSIGNED is the same as ASN_GAUGE */
  638: 		case ASN_TIMETICKS:		/* 0x43, snmp_impl.h */
  639: 		case ASN_UINTEGER:		/* 0x47, snmp_impl.h */
  640: 			snprintf(buf, buflen, "%lu", *vars->val.integer);
  641: 			buf[buflen]=0;
  642: 			ZVAL_STRING(val, buf, 1);
  643: 			break;
  644: 
  645: 		case ASN_INTEGER:		/* 0x02, asn1.h */
  646: 			snprintf(buf, buflen, "%ld", *vars->val.integer);
  647: 			buf[buflen]=0;
  648: 			ZVAL_STRING(val, buf, 1);
  649: 			break;
  650: 
  651: #if defined(NETSNMP_WITH_OPAQUE_SPECIAL_TYPES) || defined(OPAQUE_SPECIAL_TYPES)
  652: 		case ASN_OPAQUE_FLOAT:		/* 0x78, asn1.h */
  653: 			snprintf(buf, buflen, "%f", *vars->val.floatVal);
  654: 			ZVAL_STRING(val, buf, 1);
  655: 			break;
  656: 
  657: 		case ASN_OPAQUE_DOUBLE:		/* 0x79, asn1.h */
  658: 			snprintf(buf, buflen, "%Lf", *vars->val.doubleVal);
  659: 			ZVAL_STRING(val, buf, 1);
  660: 			break;
  661: 
  662: 		case ASN_OPAQUE_I64:		/* 0x80, asn1.h */
  663: 			printI64(buf, vars->val.counter64);
  664: 			ZVAL_STRING(val, buf, 1);
  665: 			break;
  666: 
  667: 		case ASN_OPAQUE_U64:		/* 0x81, asn1.h */
  668: #endif
  669: 		case ASN_COUNTER64:		/* 0x46, snmp_impl.h */
  670: 			printU64(buf, vars->val.counter64);
  671: 			ZVAL_STRING(val, buf, 1);
  672: 			break;
  673: 
  674: 		default:
  675: 			ZVAL_STRING(val, "Unknown value type", 1);
  676: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown value type: %u", vars->type);
  677: 			break;
  678: 		}
  679: 	} else /* use Net-SNMP value translation */ {
  680: 		/* we have desired string in buffer, just use it */
  681: 		ZVAL_STRING(val, buf, 1);
  682: 	}
  683: 
  684: 	if (valueretrieval & SNMP_VALUE_OBJECT) {
  685: 		object_init(snmpval);
  686: 		add_property_long(snmpval, "type", vars->type);
  687: 		add_property_zval(snmpval, "value", val);
  688: 	} else  {
  689: 		*snmpval = *val;
  690: 		zval_copy_ctor(snmpval);
  691: 	}
  692: 	zval_ptr_dtor(&val);
  693: 
  694: 	if(dbuf){ /* malloc was used to store value */
  695: 		efree(dbuf);
  696: 	}
  697: }
  698: /* }}} */
  699: 
  700: /* {{{ php_snmp_internal
  701: *
  702: * SNMP object fetcher/setter for all SNMP versions
  703: *
  704: */
  705: static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, 
  706: 							struct snmp_session *session,
  707: 							struct objid_query *objid_query)
  708: {
  709: 	struct snmp_session *ss;
  710: 	struct snmp_pdu *pdu=NULL, *response;
  711: 	struct variable_list *vars;
  712: 	oid root[MAX_NAME_LEN];
  713: 	size_t rootlen = 0;
  714: 	int status, count, found;
  715: 	char buf[2048];
  716: 	char buf2[2048];
  717: 	int keepwalking=1;
  718: 	char *err;
  719: 	zval *snmpval = NULL;
  720: 	int snmp_errno;
  721: 
  722: 	/* we start with retval=FALSE. If any actual data is acquired, retval will be set to appropriate type */
  723: 	RETVAL_FALSE;
  724: 	
  725: 	/* reset errno and errstr */
  726: 	php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_NOERROR, "");
  727: 
  728: 	if (st & SNMP_CMD_WALK) { /* remember root OID */
  729: 		memmove((char *)root, (char *)(objid_query->vars[0].name), (objid_query->vars[0].name_length) * sizeof(oid));
  730: 		rootlen = objid_query->vars[0].name_length;
  731: 		objid_query->offset = objid_query->count;
  732: 	}
  733: 
  734: 	if ((ss = snmp_open(session)) == NULL) {
  735: 		snmp_error(session, NULL, NULL, &err);
  736: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open snmp connection: %s", err);
  737: 		free(err);
  738: 		RETVAL_FALSE;
  739: 		return;
  740: 	}
  741: 
  742: 	if ((st & SNMP_CMD_SET) && objid_query->count > objid_query->step) {
  743: 		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");
  744: 	}
  745: 
  746: 	while (keepwalking) {
  747: 		keepwalking = 0;
  748: 		if (st & SNMP_CMD_WALK) {
  749: 			if (session->version == SNMP_VERSION_1) {
  750: 				pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
  751: 			} else {
  752: 				pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
  753: 				pdu->non_repeaters = objid_query->non_repeaters;
  754: 				pdu->max_repetitions = objid_query->max_repetitions;
  755: 			}
  756: 			snmp_add_null_var(pdu, objid_query->vars[0].name, objid_query->vars[0].name_length);
  757: 		} else {
  758: 			if (st & SNMP_CMD_GET) {
  759: 				pdu = snmp_pdu_create(SNMP_MSG_GET);
  760: 			} else if (st & SNMP_CMD_GETNEXT) {
  761: 				pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
  762: 			} else if (st & SNMP_CMD_SET) {
  763: 				pdu = snmp_pdu_create(SNMP_MSG_SET);
  764: 			} else {
  765: 				snmp_close(ss);
  766: 				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unknown SNMP command (internals)");
  767: 				RETVAL_FALSE;
  768: 				return;
  769: 			}
  770: 			for (count = 0; objid_query->offset < objid_query->count && count < objid_query->step; objid_query->offset++, count++){
  771: 				if (st & SNMP_CMD_SET) {
  772: 					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))) {
  773: 						snprint_objid(buf, sizeof(buf), objid_query->vars[objid_query->offset].name, objid_query->vars[objid_query->offset].name_length);
  774: 						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));
  775: 						snmp_free_pdu(pdu);
  776: 						snmp_close(ss);
  777: 						RETVAL_FALSE;
  778: 						return;
  779: 					}
  780: 				} else {
  781: 					snmp_add_null_var(pdu, objid_query->vars[objid_query->offset].name, objid_query->vars[objid_query->offset].name_length);
  782: 				}
  783: 			}
  784: 			if(pdu->variables == NULL){
  785: 				snmp_free_pdu(pdu);
  786: 				snmp_close(ss);
  787: 				RETVAL_FALSE;
  788: 				return;
  789: 			}
  790: 		}
  791: 
  792: retry:
  793: 		status = snmp_synch_response(ss, pdu, &response);
  794: 		if (status == STAT_SUCCESS) {
  795: 			if (response->errstat == SNMP_ERR_NOERROR) {
  796: 				if (st & SNMP_CMD_SET) {
  797: 					if (objid_query->offset < objid_query->count) { /* we have unprocessed OIDs */
  798: 						keepwalking = 1;
  799: 						continue;
  800: 					}
  801: 					snmp_free_pdu(response);
  802: 					snmp_close(ss);
  803: 					RETVAL_TRUE;
  804: 					return;
  805: 				}
  806: 				for (vars = response->variables; vars; vars = vars->next_variable) {
  807: 					/* do not output errors as values */
  808: 					if ( 	vars->type == SNMP_ENDOFMIBVIEW || 
  809: 						vars->type == SNMP_NOSUCHOBJECT || 
  810: 						vars->type == SNMP_NOSUCHINSTANCE ) {
  811: 						if ((st & SNMP_CMD_WALK) && Z_TYPE_P(return_value) == IS_ARRAY) {
  812: 							break;
  813: 						}
  814: 						snprint_objid(buf, sizeof(buf), vars->name, vars->name_length);
  815: 						snprint_value(buf2, sizeof(buf2), vars->name, vars->name_length, vars);
  816: 						php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_ERROR_IN_REPLY, "Error in packet at '%s': %s", buf, buf2);
  817: 						continue;
  818: 					}
  819: 					
  820: 					if ((st & SNMP_CMD_WALK) && 
  821: 						(vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid)))) { /* not part of this subtree */
  822: 						if (Z_TYPE_P(return_value) == IS_ARRAY) { /* some records are fetched already, shut down further lookup */
  823: 							keepwalking = 0;
  824: 						} else {
  825: 							/* first fetched OID is out of subtree, fallback to GET query */
  826: 							st |= SNMP_CMD_GET;
  827: 							st ^= SNMP_CMD_WALK;
  828: 							objid_query->offset = 0;
  829: 							keepwalking = 1;
  830: 						}
  831: 						break;
  832: 					}
  833: 
  834: 					MAKE_STD_ZVAL(snmpval);
  835: 					php_snmp_getvalue(vars, snmpval TSRMLS_CC, objid_query->valueretrieval);
  836: 
  837: 					if (objid_query->array_output) {
  838: 						if (Z_TYPE_P(return_value) == IS_BOOL) {
  839: 							array_init(return_value);
  840: 						}
  841: 						if (st & SNMP_NUMERIC_KEYS) {
  842: 							add_next_index_zval(return_value, snmpval);
  843: 						} else if (st & SNMP_ORIGINAL_NAMES_AS_KEYS && st & SNMP_CMD_GET) {
  844: 							found = 0;
  845: 							for (count = 0; count < objid_query->count; count++) {
  846: 								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) {
  847: 									found = 1;
  848: 									objid_query->vars[count].name_length = 0; /* mark this name as used */
  849: 									break;
  850: 								}
  851: 							}
  852: 							if (found) {
  853: 								add_assoc_zval(return_value, objid_query->vars[count].oid, snmpval);
  854: 							} else {
  855: 								snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
  856: 								php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find original OID name for '%s'", buf2);
  857: 							}
  858: 						} else if (st & SNMP_USE_SUFFIX_AS_KEYS && st & SNMP_CMD_WALK) {
  859: 							snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
  860: 							if (rootlen <= vars->name_length && snmp_oid_compare(root, rootlen, vars->name, rootlen) == 0) {
  861: 								buf2[0] = '\0';
  862: 								count = rootlen;
  863: 								while(count < vars->name_length){
  864: 									sprintf(buf, "%lu.", vars->name[count]);
  865: 									strcat(buf2, buf);
  866: 									count++;
  867: 								}
  868: 								buf2[strlen(buf2) - 1] = '\0'; /* remove trailing '.' */
  869: 							}
  870: 							add_assoc_zval(return_value, buf2, snmpval);
  871: 						} else {
  872: 							snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
  873: 							add_assoc_zval(return_value, buf2, snmpval);
  874: 						}
  875: 					} else {
  876: 						*return_value = *snmpval;
  877: 						zval_copy_ctor(return_value);
  878: 						zval_ptr_dtor(&snmpval);
  879: 						break;
  880: 					}
  881: 
  882: 					/* OID increase check */
  883: 					if (st & SNMP_CMD_WALK) {
  884: 						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) {
  885: 							snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
  886: 							php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_NOT_INCREASING, "Error: OID not increasing: %s", buf2);
  887: 							keepwalking = 0;
  888: 						} else {
  889: 							memmove((char *)(objid_query->vars[0].name), (char *)vars->name, vars->name_length * sizeof(oid));
  890: 							objid_query->vars[0].name_length = vars->name_length;
  891: 							keepwalking = 1;
  892: 						}
  893: 					}
  894: 				}
  895: 				if (objid_query->offset < objid_query->count) { /* we have unprocessed OIDs */
  896: 					keepwalking = 1;
  897: 				}
  898: 			} else {
  899: 				if (st & SNMP_CMD_WALK && response->errstat == SNMP_ERR_TOOBIG && objid_query->max_repetitions > 1) { /* Answer will not fit into single packet */
  900: 					objid_query->max_repetitions /= 2;
  901: 					snmp_free_pdu(response);
  902: 					keepwalking = 1;
  903: 					continue;
  904: 				}
  905: 				if (!(st & SNMP_CMD_WALK) || response->errstat != SNMP_ERR_NOSUCHNAME || Z_TYPE_P(return_value) == IS_BOOL) {
  906: 					for (	count=1, vars = response->variables;
  907: 						vars && count != response->errindex;
  908: 						vars = vars->next_variable, count++);
  909: 
  910: 					if (st & (SNMP_CMD_GET | SNMP_CMD_GETNEXT) && response->errstat == SNMP_ERR_TOOBIG && objid_query->step > 1) { /* Answer will not fit into single packet */
  911: 						objid_query->offset = ((objid_query->offset > objid_query->step) ? (objid_query->offset - objid_query->step) : 0 );
  912: 						objid_query->step /= 2;
  913: 						snmp_free_pdu(response);
  914: 						keepwalking = 1;
  915: 						continue;
  916: 					}
  917: 					if (vars) {
  918: 						snprint_objid(buf, sizeof(buf), vars->name, vars->name_length);
  919: 						php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_ERROR_IN_REPLY, "Error in packet at '%s': %s", buf, snmp_errstring(response->errstat));
  920: 					} else {
  921: 						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));
  922: 					}
  923: 					if (st & (SNMP_CMD_GET | SNMP_CMD_GETNEXT)) { /* cut out bogus OID and retry */
  924: 						if ((pdu = snmp_fix_pdu(response, ((st & SNMP_CMD_GET) ? SNMP_MSG_GET : SNMP_MSG_GETNEXT) )) != NULL) {
  925: 							snmp_free_pdu(response);
  926: 							goto retry;
  927: 						}
  928: 					}
  929: 					snmp_free_pdu(response);
  930: 					snmp_close(ss);
  931: 					if (objid_query->array_output) {
  932: 						zval_dtor(return_value);
  933: 					}
  934: 					RETVAL_FALSE;
  935: 					return;
  936: 				}
  937: 			}
  938: 		} else if (status == STAT_TIMEOUT) {
  939: 			php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_TIMEOUT, "No response from %s", session->peername);
  940: 			if (objid_query->array_output) {
  941: 				zval_dtor(return_value);
  942: 			}
  943: 			snmp_close(ss);
  944: 			RETVAL_FALSE;
  945: 			return;
  946: 		} else {    /* status == STAT_ERROR */
  947: 			snmp_error(ss, NULL, NULL, &err);
  948: 			php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_GENERIC, "Fatal error: %s", err);
  949: 			free(err);
  950: 			if (objid_query->array_output) {
  951: 				zval_dtor(return_value);
  952: 			}
  953: 			snmp_close(ss);
  954: 			RETVAL_FALSE;
  955: 			return;
  956: 		}
  957: 		if (response) {
  958: 			snmp_free_pdu(response);
  959: 		}
  960: 	} /* keepwalking */
  961: 	snmp_close(ss);
  962: }
  963: /* }}} */
  964: 
  965: /* {{{ php_snmp_parse_oid
  966: *
  967: * OID parser (and type, value for SNMP_SET command)
  968: */
  969: 
  970: static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_query, zval **oid, zval **type, zval **value TSRMLS_DC)
  971: {
  972: 	char *pptr;
  973: 	HashPosition pos_oid, pos_type, pos_value;
  974: 	zval **tmp_oid, **tmp_type, **tmp_value;
  975: 
  976: 	if (Z_TYPE_PP(oid) != IS_ARRAY) {
  977: 		if (Z_ISREF_PP(oid)) {
  978: 			SEPARATE_ZVAL(oid);
  979: 		}
  980: 		convert_to_string_ex(oid);
  981: 	} else if (Z_TYPE_PP(oid) == IS_ARRAY) {
  982: 		zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(oid), &pos_oid);
  983: 	}
  984: 
  985: 	if (st & SNMP_CMD_SET) {
  986: 		if (Z_TYPE_PP(type) != IS_ARRAY) {
  987: 			if (Z_ISREF_PP(type)) {
  988: 				SEPARATE_ZVAL(type);
  989: 			}
  990: 			convert_to_string_ex(type);
  991: 		} else if (Z_TYPE_PP(type) == IS_ARRAY) {
  992: 			zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(type), &pos_type);
  993: 		}
  994: 
  995: 		if (Z_TYPE_PP(value) != IS_ARRAY) {
  996: 			if (Z_ISREF_PP(value)) {
  997: 				SEPARATE_ZVAL(value);
  998: 			}
  999: 			convert_to_string_ex(value);
 1000: 		} else if (Z_TYPE_PP(value) == IS_ARRAY) {
 1001: 			zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(value), &pos_value);
 1002: 		}
 1003: 	}
 1004: 
 1005: 	objid_query->count = 0;
 1006: 	objid_query->array_output = ((st & SNMP_CMD_WALK) ? TRUE : FALSE);
 1007: 	if (Z_TYPE_PP(oid) == IS_STRING) {
 1008: 		objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg));
 1009: 		if (objid_query->vars == NULL) {
 1010: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while parsing oid: %s", strerror(errno));
 1011: 			efree(objid_query->vars);
 1012: 			return FALSE;
 1013: 		}
 1014: 		objid_query->vars[objid_query->count].oid = Z_STRVAL_PP(oid);
 1015: 		if (st & SNMP_CMD_SET) {
 1016: 			if (Z_TYPE_PP(type) == IS_STRING && Z_TYPE_PP(value) == IS_STRING) {
 1017: 				if (Z_STRLEN_PP(type) != 1) {
 1018: 					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));
 1019: 					efree(objid_query->vars);
 1020: 					return FALSE;
 1021: 				}
 1022: 				pptr = Z_STRVAL_PP(type);
 1023: 				objid_query->vars[objid_query->count].type = *pptr;
 1024: 				objid_query->vars[objid_query->count].value = Z_STRVAL_PP(value);
 1025: 			} else {
 1026: 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Single objid and multiple type or values are not supported");
 1027: 				efree(objid_query->vars);
 1028: 				return FALSE;
 1029: 			}
 1030: 		}
 1031: 		objid_query->count++;
 1032: 	} else if (Z_TYPE_PP(oid) == IS_ARRAY) { /* we got objid array */
 1033: 		if (zend_hash_num_elements(Z_ARRVAL_PP(oid)) == 0) {
 1034: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Got empty OID array");
 1035: 			return FALSE;
 1036: 		}
 1037: 		objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_PP(oid)));
 1038: 		if (objid_query->vars == NULL) {
 1039: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno));
 1040: 			efree(objid_query->vars);
 1041: 			return FALSE;
 1042: 		}
 1043: 		objid_query->array_output = ( (st & SNMP_CMD_SET) ? FALSE : TRUE );
 1044: 		for (	zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(oid), &pos_oid);
 1045: 			zend_hash_get_current_data_ex(Z_ARRVAL_PP(oid), (void **) &tmp_oid, &pos_oid) == SUCCESS;
 1046: 			zend_hash_move_forward_ex(Z_ARRVAL_PP(oid), &pos_oid) ) {
 1047: 
 1048: 			convert_to_string_ex(tmp_oid);
 1049: 			objid_query->vars[objid_query->count].oid = Z_STRVAL_PP(tmp_oid);
 1050: 			if (st & SNMP_CMD_SET) {
 1051: 				if (Z_TYPE_PP(type) == IS_STRING) {
 1052: 					pptr = Z_STRVAL_PP(type);
 1053: 					objid_query->vars[objid_query->count].type = *pptr;
 1054: 				} else if (Z_TYPE_PP(type) == IS_ARRAY) {
 1055: 					if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(type), (void **) &tmp_type, &pos_type)) {
 1056: 						convert_to_string_ex(tmp_type);
 1057: 						if (Z_STRLEN_PP(tmp_type) != 1) {
 1058: 							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));
 1059: 							efree(objid_query->vars);
 1060: 							return FALSE;
 1061: 						}
 1062: 						pptr = Z_STRVAL_PP(tmp_type);
 1063: 						objid_query->vars[objid_query->count].type = *pptr;
 1064: 						zend_hash_move_forward_ex(Z_ARRVAL_PP(type), &pos_type);
 1065: 					} else {
 1066: 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s': no type set", Z_STRVAL_PP(tmp_oid));
 1067: 						efree(objid_query->vars);
 1068: 						return FALSE;
 1069: 					}
 1070: 				}
 1071: 
 1072: 				if (Z_TYPE_PP(value) == IS_STRING) {
 1073: 					objid_query->vars[objid_query->count].value = Z_STRVAL_PP(value);
 1074: 				} else if (Z_TYPE_PP(value) == IS_ARRAY) {
 1075: 					if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(value), (void **) &tmp_value, &pos_value)) {
 1076: 						convert_to_string_ex(tmp_value);
 1077: 						objid_query->vars[objid_query->count].value = Z_STRVAL_PP(tmp_value);
 1078: 						zend_hash_move_forward_ex(Z_ARRVAL_PP(value), &pos_value);
 1079: 					} else {
 1080: 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s': no value set", Z_STRVAL_PP(tmp_oid));
 1081: 						efree(objid_query->vars);
 1082: 						return FALSE;
 1083: 					}
 1084: 				}
 1085: 			}
 1086: 			objid_query->count++;
 1087: 		}
 1088: 	}
 1089: 
 1090: 	/* now parse all OIDs */
 1091: 	if (st & SNMP_CMD_WALK) {
 1092: 		if (objid_query->count > 1) {
 1093: 			php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Multi OID walks are not supported!");
 1094: 			efree(objid_query->vars);
 1095: 			return FALSE;
 1096: 		}
 1097: 		objid_query->vars[0].name_length = MAX_NAME_LEN;
 1098: 		if (strlen(objid_query->vars[0].oid)) { /* on a walk, an empty string means top of tree - no error */
 1099: 			if (!snmp_parse_oid(objid_query->vars[0].oid, objid_query->vars[0].name, &(objid_query->vars[0].name_length))) {
 1100: 				php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[0].oid);
 1101: 				efree(objid_query->vars);
 1102: 				return FALSE;
 1103: 			}
 1104: 		} else { 
 1105: 			memmove((char *)objid_query->vars[0].name, (char *)objid_mib, sizeof(objid_mib));
 1106: 			objid_query->vars[0].name_length = sizeof(objid_mib) / sizeof(oid);
 1107: 		}
 1108: 	} else {
 1109: 		for (objid_query->offset = 0; objid_query->offset < objid_query->count; objid_query->offset++) {
 1110: 			objid_query->vars[objid_query->offset].name_length = MAX_OID_LEN;
 1111: 			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))) {
 1112: 				php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[objid_query->offset].oid);
 1113: 				efree(objid_query->vars);
 1114: 				return FALSE;
 1115: 			}
 1116: 		}
 1117: 	}
 1118: 	objid_query->offset = 0;
 1119: 	objid_query->step = objid_query->count;
 1120: 	return (objid_query->count > 0);
 1121: }
 1122: /* }}} */
 1123: 
 1124: /* {{{ netsnmp_session_init
 1125: 	allocates memory for session and session->peername, caller should free it manually using netsnmp_session_free() and efree()
 1126: */
 1127: static int netsnmp_session_init(php_snmp_session **session_p, int version, char *hostname, char *community, int timeout, int retries TSRMLS_DC)
 1128: {
 1129: 	php_snmp_session *session;
 1130: 	char *pptr, *host_ptr;
 1131: 	int force_ipv6 = FALSE;
 1132: 	int n;
 1133: 	struct sockaddr **psal;
 1134: 	struct sockaddr **res;
 1135: 
 1136: 	*session_p = (php_snmp_session *)emalloc(sizeof(php_snmp_session));
 1137: 	session = *session_p;
 1138: 	if (session == NULL) {
 1139: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed allocating session");
 1140: 		return (-1);
 1141: 	}
 1142: 	memset(session, 0, sizeof(php_snmp_session));
 1143: 
 1144: 	snmp_sess_init(session);
 1145: 
 1146: 	session->version = version;
 1147: 	session->remote_port = SNMP_PORT;
 1148: 
 1149: 	session->peername = emalloc(MAX_NAME_LEN);
 1150: 	if (session->peername == NULL) {
 1151: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while copying hostname");
 1152: 		return (-1);
 1153: 	}
 1154: 	/* we copy original hostname for further processing */
 1155: 	strlcpy(session->peername, hostname, MAX_NAME_LEN);
 1156: 	host_ptr = session->peername;
 1157: 
 1158: 	/* Reading the hostname and its optional non-default port number */
 1159: 	if (*host_ptr == '[') { /* IPv6 address */
 1160: 		force_ipv6 = TRUE;
 1161: 		host_ptr++;
 1162: 		if ((pptr = strchr(host_ptr, ']'))) {
 1163: 			if (pptr[1] == ':') {
 1164: 				session->remote_port = atoi(pptr + 2);
 1165: 			}
 1166: 			*pptr = '\0';
 1167: 		} else {
 1168: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "malformed IPv6 address, closing square bracket missing");
 1169: 			return (-1);
 1170: 		}
 1171: 	} else { /* IPv4 address */
 1172: 		if ((pptr = strchr(host_ptr, ':'))) {
 1173: 			session->remote_port = atoi(pptr + 1);
 1174: 			*pptr = '\0';
 1175: 		}
 1176: 	}
 1177: 
 1178: 	/* since Net-SNMP library requires 'udp6:' prefix for all IPv6 addresses (in FQDN form too) we need to
 1179: 	   perform possible name resolution before running any SNMP queries */
 1180: 	if ((n = php_network_getaddresses(host_ptr, SOCK_DGRAM, &psal, NULL TSRMLS_CC)) == 0) { /* some resolver error */
 1181: 		/* warnings sent, bailing out */
 1182: 		return (-1);
 1183: 	}
 1184: 
 1185: 	/* we have everything we need in psal, flush peername and fill it properly */
 1186: 	*(session->peername) = '\0';
 1187: 	res = psal;
 1188: 	while (n-- > 0) {
 1189: 		pptr = session->peername;
 1190: #if HAVE_GETADDRINFO && HAVE_IPV6 && HAVE_INET_NTOP
 1191: 		if (force_ipv6 && (*res)->sa_family != AF_INET6) {
 1192: 			res++;
 1193: 			continue;
 1194: 		}
 1195: 		if ((*res)->sa_family == AF_INET6) {
 1196: 			strcpy(session->peername, "udp6:[");
 1197: 			pptr = session->peername + strlen(session->peername);
 1198: 			inet_ntop((*res)->sa_family, &(((struct sockaddr_in6*)(*res))->sin6_addr), pptr, MAX_NAME_LEN);
 1199: 			strcat(pptr, "]");
 1200: 		} else if ((*res)->sa_family == AF_INET) {
 1201: 			inet_ntop((*res)->sa_family, &(((struct sockaddr_in*)(*res))->sin_addr), pptr, MAX_NAME_LEN);
 1202: 		} else {
 1203: 			res++;
 1204: 			continue;
 1205: 		}
 1206: #else
 1207: 		if ((*res)->sa_family != AF_INET) {
 1208: 			res++;
 1209: 			continue;
 1210: 		}
 1211: 		strcat(pptr, inet_ntoa(((struct sockaddr_in*)(*res))->sin_addr));
 1212: #endif
 1213: 		break;
 1214: 	}
 1215: 
 1216: 	if (strlen(session->peername) == 0) {
 1217: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown failure while resolving '%s'", hostname);
 1218: 		return (-1);
 1219: 	}
 1220: 	/* XXX FIXME
 1221: 		There should be check for non-empty session->peername!
 1222: 	*/
 1223: 
 1224: 	/* put back non-standard SNMP port */
 1225: 	if (session->remote_port != SNMP_PORT) {
 1226: 		pptr = session->peername + strlen(session->peername);
 1227: 		sprintf(pptr, ":%d", session->remote_port);
 1228: 	}
 1229: 
 1230: 	php_network_freeaddresses(psal);
 1231: 
 1232: 	if (version == SNMP_VERSION_3) {
 1233: 		/* Setting the security name. */
 1234: 		session->securityName = estrdup(community);
 1235: 		session->securityNameLen = strlen(session->securityName);
 1236: 	} else {
 1237: 		session->authenticator = NULL;
 1238: 		session->community = (u_char *)estrdup(community);
 1239: 		session->community_len = strlen(community);
 1240: 	}
 1241: 
 1242: 	session->retries = retries;
 1243: 	session->timeout = timeout;
 1244: 	return (0);
 1245: }
 1246: /* }}} */
 1247: 
 1248: /* {{{ int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
 1249:    Set the security level in the snmpv3 session */
 1250: static int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
 1251: {
 1252: 	if (!strcasecmp(level, "noAuthNoPriv") || !strcasecmp(level, "nanp")) {
 1253: 		s->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
 1254: 	} else if (!strcasecmp(level, "authNoPriv") || !strcasecmp(level, "anp")) {
 1255: 		s->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
 1256: 	} else if (!strcasecmp(level, "authPriv") || !strcasecmp(level, "ap")) {
 1257: 		s->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
 1258: 	} else {
 1259: 		return (-1);
 1260: 	}
 1261: 	return (0);
 1262: }
 1263: /* }}} */
 1264: 
 1265: /* {{{ int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot)
 1266:    Set the authentication protocol in the snmpv3 session */
 1267: static int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
 1268: {
 1269: 	if (!strcasecmp(prot, "MD5")) {
 1270: 		s->securityAuthProto = usmHMACMD5AuthProtocol;
 1271: 		s->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
 1272: 	} else if (!strcasecmp(prot, "SHA")) {
 1273: 		s->securityAuthProto = usmHMACSHA1AuthProtocol;
 1274: 		s->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
 1275: 	} else {
 1276: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown authentication protocol '%s'", prot);
 1277: 		return (-1);
 1278: 	}
 1279: 	return (0);
 1280: }
 1281: /* }}} */
 1282: 
 1283: /* {{{ int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot)
 1284:    Set the security protocol in the snmpv3 session */
 1285: static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
 1286: {
 1287: 	if (!strcasecmp(prot, "DES")) {
 1288: 		s->securityPrivProto = usmDESPrivProtocol;
 1289: 		s->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
 1290: #ifdef HAVE_AES
 1291: 	} else if (!strcasecmp(prot, "AES128") || !strcasecmp(prot, "AES")) {
 1292: 		s->securityPrivProto = usmAESPrivProtocol;
 1293: 		s->securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN;
 1294: #endif
 1295: 	} else {
 1296: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown security protocol '%s'", prot);
 1297: 		return (-1);
 1298: 	}
 1299: 	return (0);
 1300: }
 1301: /* }}} */
 1302: 
 1303: /* {{{ int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass)
 1304:    Make key from pass phrase in the snmpv3 session */
 1305: static int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass TSRMLS_DC)
 1306: {
 1307: 	int snmp_errno;
 1308: 	s->securityAuthKeyLen = USM_AUTH_KU_LEN;
 1309: 	if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
 1310: 			(u_char *) pass, strlen(pass),
 1311: 			s->securityAuthKey, &(s->securityAuthKeyLen)))) {
 1312: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for authentication pass phrase '%s': %s", pass, snmp_api_errstring(snmp_errno));
 1313: 		return (-1);
 1314: 	}
 1315: 	return (0);
 1316: }
 1317: /* }}} */
 1318: 
 1319: /* {{{ int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass)
 1320:    Make key from pass phrase in the snmpv3 session */
 1321: static int netsnmp_session_gen_sec_key(struct snmp_session *s, char *pass TSRMLS_DC)
 1322: {
 1323: 	int snmp_errno;
 1324: 
 1325: 	s->securityPrivKeyLen = USM_PRIV_KU_LEN;
 1326: 	if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
 1327: 			(u_char *)pass, strlen(pass),
 1328: 			s->securityPrivKey, &(s->securityPrivKeyLen)))) {
 1329: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for privacy pass phrase '%s': %s", pass, snmp_api_errstring(snmp_errno));
 1330: 		return (-2);
 1331: 	}
 1332: 	return (0);
 1333: }
 1334: /* }}} */
 1335: 
 1336: /* {{{ in netsnmp_session_set_contextEngineID(struct snmp_session *s, u_char * contextEngineID)
 1337:    Set context Engine Id in the snmpv3 session */
 1338: static int netsnmp_session_set_contextEngineID(struct snmp_session *s, char * contextEngineID TSRMLS_DC)
 1339: {
 1340: 	size_t	ebuf_len = 32, eout_len = 0;
 1341: 	u_char	*ebuf = (u_char *) emalloc(ebuf_len);
 1342: 
 1343: 	if (ebuf == NULL) {
 1344: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "malloc failure setting contextEngineID");
 1345: 		return (-1);
 1346: 	}
 1347: 	if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, contextEngineID)) {
 1348: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad engine ID value '%s'", contextEngineID);
 1349: 		efree(ebuf);
 1350: 		return (-1);
 1351: 	}
 1352: 
 1353: 	if (s->contextEngineID) {
 1354: 		efree(s->contextEngineID);
 1355: 	}
 1356: 
 1357: 	s->contextEngineID = ebuf;
 1358: 	s->contextEngineIDLen = eout_len;
 1359: 	return (0);
 1360: }
 1361: /* }}} */
 1362: 
 1363: /* {{{ 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)
 1364:    Set all snmpv3-related security options */
 1365: 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)
 1366: {
 1367: 
 1368: 	/* Setting the security level. */
 1369: 	if (netsnmp_session_set_sec_level(session, sec_level)) {
 1370: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security level '%s'", sec_level);
 1371: 		return (-1);
 1372: 	}
 1373: 
 1374: 	if (session->securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
 1375: 
 1376: 		/* Setting the authentication protocol. */
 1377: 		if (netsnmp_session_set_auth_protocol(session, auth_protocol TSRMLS_CC)) {
 1378: 			/* Warning message sent already, just bail out */
 1379: 			return (-1);
 1380: 		}
 1381: 
 1382: 		/* Setting the authentication passphrase. */
 1383: 		if (netsnmp_session_gen_auth_key(session, auth_passphrase TSRMLS_CC)) {
 1384: 			/* Warning message sent already, just bail out */
 1385: 			return (-1);
 1386: 		}
 1387: 
 1388: 		if (session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
 1389: 			/* Setting the security protocol. */
 1390: 			if (netsnmp_session_set_sec_protocol(session, priv_protocol TSRMLS_CC)) {
 1391: 				/* Warning message sent already, just bail out */
 1392: 				return (-1);
 1393: 			}
 1394: 
 1395: 			/* Setting the security protocol passphrase. */
 1396: 			if (netsnmp_session_gen_sec_key(session, priv_passphrase TSRMLS_CC)) {
 1397: 				/* Warning message sent already, just bail out */
 1398: 				return (-1);
 1399: 			}
 1400: 		}
 1401: 	}
 1402: 
 1403: 	/* Setting contextName if specified */
 1404: 	if (contextName) {
 1405: 		session->contextName = contextName;
 1406: 		session->contextNameLen = strlen(contextName);
 1407: 	}
 1408: 
 1409: 	/* Setting contextEngineIS if specified */
 1410: 	if (contextEngineID && strlen(contextEngineID) && netsnmp_session_set_contextEngineID(session, contextEngineID TSRMLS_CC)) {
 1411: 		/* Warning message sent already, just bail out */
 1412: 		return (-1);
 1413: 	}
 1414: 
 1415: 	return (0);
 1416: }
 1417: /* }}} */
 1418: 
 1419: /* {{{ php_snmp
 1420: *
 1421: * Generic SNMP handler for all versions.
 1422: * This function makes use of the internal SNMP object fetcher.
 1423: * Used both in old (non-OO) and OO API
 1424: *
 1425: */
 1426: static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 1427: {
 1428: 	zval **oid, **value, **type;
 1429: 	char *a1, *a2, *a3, *a4, *a5, *a6, *a7;
 1430: 	int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len;
 1431: 	zend_bool use_orignames = 0, suffix_keys = 0;
 1432: 	long timeout = SNMP_DEFAULT_TIMEOUT;
 1433: 	long retries = SNMP_DEFAULT_RETRIES;
 1434: 	int argc = ZEND_NUM_ARGS();
 1435: 	struct objid_query objid_query;
 1436: 	php_snmp_session *session;
 1437: 	int session_less_mode = (getThis() == NULL);
 1438: 	php_snmp_object *snmp_object;
 1439: 	php_snmp_object glob_snmp_object;
 1440: 	
 1441: 	objid_query.max_repetitions = -1;
 1442: 	objid_query.non_repeaters = 0;
 1443: 	objid_query.valueretrieval = SNMP_G(valueretrieval);
 1444: 	objid_query.oid_increasing_check = TRUE;
 1445: 
 1446: 	if (session_less_mode) {
 1447: 		if (version == SNMP_VERSION_3) {
 1448: 			if (st & SNMP_CMD_SET) {
 1449: 				if (zend_parse_parameters(argc TSRMLS_CC, "sssssssZZZ|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 1450: 					&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &oid, &type, &value, &timeout, &retries) == FAILURE) {
 1451: 					RETURN_FALSE;
 1452: 				}
 1453: 			} else {
 1454: 				/* SNMP_CMD_GET
 1455: 				 * SNMP_CMD_GETNEXT
 1456: 				 * SNMP_CMD_WALK
 1457: 				 */
 1458: 				if (zend_parse_parameters(argc TSRMLS_CC, "sssssssZ|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 1459: 					&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &oid, &timeout, &retries) == FAILURE) {
 1460: 					RETURN_FALSE;
 1461: 				}
 1462: 			}
 1463: 		} else {
 1464: 			if (st & SNMP_CMD_SET) {
 1465: 				if (zend_parse_parameters(argc TSRMLS_CC, "ssZZZ|ll", &a1, &a1_len, &a2, &a2_len, &oid, &type, &value, &timeout, &retries) == FAILURE) {
 1466: 					RETURN_FALSE;
 1467: 				}
 1468: 			} else {
 1469: 				/* SNMP_CMD_GET
 1470: 				 * SNMP_CMD_GETNEXT
 1471: 				 * SNMP_CMD_WALK
 1472: 				 */
 1473: 				if (zend_parse_parameters(argc TSRMLS_CC, "ssZ|ll", &a1, &a1_len, &a2, &a2_len, &oid, &timeout, &retries) == FAILURE) {
 1474: 					RETURN_FALSE;
 1475: 				}
 1476: 			}
 1477: 		}
 1478: 	} else {
 1479: 		if (st & SNMP_CMD_SET) {
 1480: 			if (zend_parse_parameters(argc TSRMLS_CC, "ZZZ", &oid, &type, &value) == FAILURE) {
 1481: 				RETURN_FALSE;
 1482: 			}
 1483: 		} else if (st & SNMP_CMD_WALK) {
 1484: 			if (zend_parse_parameters(argc TSRMLS_CC, "Z|bll", &oid, &suffix_keys, &(objid_query.max_repetitions), &(objid_query.non_repeaters)) == FAILURE) {
 1485: 				RETURN_FALSE;
 1486: 			}
 1487: 			if (suffix_keys) {
 1488: 				st |= SNMP_USE_SUFFIX_AS_KEYS;
 1489: 			}
 1490: 		} else if (st & SNMP_CMD_GET) {
 1491: 			if (zend_parse_parameters(argc TSRMLS_CC, "Z|b", &oid, &use_orignames) == FAILURE) {
 1492: 				RETURN_FALSE;
 1493: 			}
 1494: 			if (use_orignames) {
 1495: 				st |= SNMP_ORIGINAL_NAMES_AS_KEYS;
 1496: 			}
 1497: 		} else {
 1498: 			/* SNMP_CMD_GETNEXT
 1499: 			 */
 1500: 			if (zend_parse_parameters(argc TSRMLS_CC, "Z", &oid) == FAILURE) {
 1501: 				RETURN_FALSE;
 1502: 			}
 1503: 		}
 1504: 	}
 1505: 
 1506: 	if (!php_snmp_parse_oid(getThis(), st, &objid_query, oid, type, value TSRMLS_CC)) {
 1507: 		RETURN_FALSE;
 1508: 	}
 1509: 
 1510: 	if (session_less_mode) {
 1511: 		if (netsnmp_session_init(&session, version, a1, a2, timeout, retries TSRMLS_CC)) {
 1512: 			efree(objid_query.vars);
 1513: 			netsnmp_session_free(&session);
 1514: 			RETURN_FALSE;
 1515: 		}
 1516: 		if (version == SNMP_VERSION_3 && netsnmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL TSRMLS_CC)) {
 1517: 			efree(objid_query.vars);
 1518: 			netsnmp_session_free(&session);
 1519: 			/* Warning message sent already, just bail out */
 1520: 			RETURN_FALSE;
 1521: 		}
 1522: 	} else {
 1523: 		zval *object = getThis();
 1524: 		snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1525: 		session = snmp_object->session;
 1526: 		if (!session) {
 1527: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or uninitialized SNMP object");
 1528: 			efree(objid_query.vars);
 1529: 			RETURN_FALSE;
 1530: 		}
 1531: 
 1532: 		if (snmp_object->max_oids > 0) {
 1533: 			objid_query.step = snmp_object->max_oids;
 1534: 			if (objid_query.max_repetitions < 0) { /* unspecified in function call, use session-wise */
 1535: 				objid_query.max_repetitions = snmp_object->max_oids;
 1536: 			}
 1537: 		}
 1538: 		objid_query.oid_increasing_check = snmp_object->oid_increasing_check;
 1539: 		objid_query.valueretrieval = snmp_object->valueretrieval;
 1540: 		glob_snmp_object.enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
 1541: 		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, snmp_object->enum_print);
 1542: 		glob_snmp_object.quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
 1543: 		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, snmp_object->quick_print);
 1544: 		glob_snmp_object.oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 1545: 		netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, snmp_object->oid_output_format);
 1546: 	}
 1547: 
 1548: 	if (objid_query.max_repetitions < 0) {
 1549: 		objid_query.max_repetitions = 20; /* provide correct default value */
 1550: 	}
 1551: 
 1552: 	php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, session, &objid_query);
 1553: 	
 1554: 	efree(objid_query.vars);
 1555: 
 1556: 	if (session_less_mode) {
 1557: 		netsnmp_session_free(&session);
 1558: 	} else {
 1559: 		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, glob_snmp_object.enum_print);
 1560: 		netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, glob_snmp_object.quick_print);
 1561: 		netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, glob_snmp_object.oid_output_format);
 1562: 	}
 1563: }
 1564: /* }}} */
 1565: 
 1566: /* {{{ proto mixed snmpget(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1567:    Fetch a SNMP object */
 1568: PHP_FUNCTION(snmpget)
 1569: {
 1570: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_1);
 1571: }
 1572: /* }}} */
 1573: 
 1574: /* {{{ proto mixed snmpgetnext(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1575:    Fetch a SNMP object */
 1576: PHP_FUNCTION(snmpgetnext)
 1577: {
 1578: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_1);
 1579: }
 1580: /* }}} */
 1581: 
 1582: /* {{{ proto mixed snmpwalk(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1583:    Return all objects under the specified object id */
 1584: PHP_FUNCTION(snmpwalk)
 1585: {
 1586: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_1);
 1587: }
 1588: /* }}} */
 1589: 
 1590: /* {{{ proto mixed snmprealwalk(string host, string community, mixed object_id [, int timeout [, int retries]])
 1591:    Return all objects including their respective object id withing the specified one */
 1592: PHP_FUNCTION(snmprealwalk)
 1593: {
 1594: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_1);
 1595: }
 1596: /* }}} */
 1597: 
 1598: /* {{{ proto bool snmpset(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) 
 1599:    Set the value of a SNMP object */
 1600: PHP_FUNCTION(snmpset)
 1601: {
 1602: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_1);
 1603: }
 1604: /* }}} */
 1605: 
 1606: /* {{{ proto bool snmp_get_quick_print(void)
 1607:    Return the current status of quick_print */
 1608: PHP_FUNCTION(snmp_get_quick_print)
 1609: {
 1610: 	if (zend_parse_parameters_none() == FAILURE) {
 1611: 		return;
 1612: 	}
 1613: 
 1614: 	RETURN_BOOL(netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT));
 1615: }
 1616: /* }}} */
 1617: 
 1618: /* {{{ proto bool snmp_set_quick_print(int quick_print)
 1619:    Return all objects including their respective object id withing the specified one */
 1620: PHP_FUNCTION(snmp_set_quick_print)
 1621: {
 1622: 	long a1;
 1623: 
 1624: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 1625: 		RETURN_FALSE;
 1626: 	}
 1627: 
 1628: 	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, (int)a1);
 1629: 	RETURN_TRUE;
 1630: }
 1631: /* }}} */
 1632: 
 1633: /* {{{ proto bool snmp_set_enum_print(int enum_print)
 1634:    Return all values that are enums with their enum value instead of the raw integer */
 1635: PHP_FUNCTION(snmp_set_enum_print)
 1636: {
 1637: 	long a1;
 1638: 
 1639: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 1640: 		RETURN_FALSE;
 1641: 	}
 1642: 
 1643: 	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, (int) a1);
 1644: 	RETURN_TRUE;
 1645: } 
 1646: /* }}} */
 1647: 
 1648: /* {{{ proto bool snmp_set_oid_output_format(int oid_format)
 1649:    Set the OID output format. */
 1650: PHP_FUNCTION(snmp_set_oid_output_format)
 1651: {
 1652: 	long a1;
 1653: 
 1654: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
 1655: 		RETURN_FALSE;
 1656: 	}
 1657: 
 1658: 	switch((int) a1) {
 1659: 		case NETSNMP_OID_OUTPUT_SUFFIX:
 1660: 		case NETSNMP_OID_OUTPUT_MODULE:
 1661: 		case NETSNMP_OID_OUTPUT_FULL:
 1662: 		case NETSNMP_OID_OUTPUT_NUMERIC:
 1663: 		case NETSNMP_OID_OUTPUT_UCD:
 1664: 		case NETSNMP_OID_OUTPUT_NONE:
 1665: 			netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, a1);
 1666: 			RETURN_TRUE;
 1667: 			break;
 1668: 		default:
 1669: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP output print format '%d'", (int) a1);
 1670: 			RETURN_FALSE;
 1671: 			break;
 1672: 	}
 1673: } 
 1674: /* }}} */
 1675: 
 1676: /* {{{ proto mixed snmp2_get(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1677:    Fetch a SNMP object */
 1678: PHP_FUNCTION(snmp2_get)
 1679: {
 1680: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_2c);
 1681: }
 1682: /* }}} */
 1683: 
 1684: /* {{{ proto mixed snmp2_getnext(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1685:    Fetch a SNMP object */
 1686: PHP_FUNCTION(snmp2_getnext)
 1687: {
 1688: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_2c);
 1689: }
 1690: /* }}} */
 1691: 
 1692: /* {{{ proto mixed snmp2_walk(string host, string community, mixed object_id [, int timeout [, int retries]]) 
 1693:    Return all objects under the specified object id */
 1694: PHP_FUNCTION(snmp2_walk)
 1695: {
 1696: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_2c);
 1697: }
 1698: /* }}} */
 1699: 
 1700: /* {{{ proto mixed snmp2_real_walk(string host, string community, mixed object_id [, int timeout [, int retries]])
 1701:    Return all objects including their respective object id withing the specified one */
 1702: PHP_FUNCTION(snmp2_real_walk)
 1703: {
 1704: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_2c);
 1705: }
 1706: /* }}} */
 1707: 
 1708: /* {{{ proto bool snmp2_set(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]]) 
 1709:    Set the value of a SNMP object */
 1710: PHP_FUNCTION(snmp2_set)
 1711: {
 1712: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_2c);
 1713: }
 1714: /* }}} */
 1715: 
 1716: /* {{{ 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]])
 1717:    Fetch the value of a SNMP object */
 1718: PHP_FUNCTION(snmp3_get)
 1719: {
 1720: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_3);
 1721: }
 1722: /* }}} */
 1723: 
 1724: /* {{{ 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]])
 1725:    Fetch the value of a SNMP object */
 1726: PHP_FUNCTION(snmp3_getnext)
 1727: {
 1728: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_3);
 1729: }
 1730: /* }}} */
 1731: 
 1732: /* {{{ 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]])
 1733:    Fetch the value of a SNMP object */
 1734: PHP_FUNCTION(snmp3_walk)
 1735: {
 1736: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_3);
 1737: }
 1738: /* }}} */
 1739: 
 1740: /* {{{ 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]])
 1741:    Fetch the value of a SNMP object */
 1742: PHP_FUNCTION(snmp3_real_walk)
 1743: {
 1744: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_3);
 1745: }
 1746: /* }}} */
 1747: 
 1748: /* {{{ 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]])
 1749:    Fetch the value of a SNMP object */
 1750: PHP_FUNCTION(snmp3_set)
 1751: {
 1752: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_3);
 1753: }
 1754: /* }}} */
 1755: 
 1756: /* {{{ proto bool snmp_set_valueretrieval(int method)
 1757:    Specify the method how the SNMP values will be returned */
 1758: PHP_FUNCTION(snmp_set_valueretrieval)
 1759: {
 1760: 	long method;
 1761: 
 1762: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
 1763: 		RETURN_FALSE;
 1764: 	}
 1765: 
 1766: 	if (method >= 0 && method <= (SNMP_VALUE_LIBRARY|SNMP_VALUE_PLAIN|SNMP_VALUE_OBJECT)) {
 1767: 			SNMP_G(valueretrieval) = method;
 1768: 			RETURN_TRUE;
 1769: 	} else {
 1770: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP value retrieval method '%ld'", method);
 1771: 		RETURN_FALSE;
 1772: 	}
 1773: }
 1774: /* }}} */
 1775: 
 1776: /* {{{ proto int snmp_get_valueretrieval()
 1777:    Return the method how the SNMP values will be returned */
 1778: PHP_FUNCTION(snmp_get_valueretrieval)
 1779: {
 1780: 	if (zend_parse_parameters_none() == FAILURE) {
 1781: 		RETURN_FALSE;
 1782: 	}
 1783: 
 1784: 	RETURN_LONG(SNMP_G(valueretrieval));
 1785: }
 1786: /* }}} */
 1787: 
 1788: /* {{{ proto bool snmp_read_mib(string filename)
 1789:    Reads and parses a MIB file into the active MIB tree. */
 1790: PHP_FUNCTION(snmp_read_mib)
 1791: {
 1792: 	char *filename;
 1793: 	int filename_len;
 1794: 
 1795: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
 1796: 		RETURN_FALSE;
 1797: 	}
 1798: 
 1799: 	if (!read_mib(filename)) {
 1800: 		char *error = strerror(errno);
 1801: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading MIB file '%s': %s", filename, error);
 1802: 		RETURN_FALSE;
 1803: 	}
 1804: 	RETURN_TRUE;
 1805: }
 1806: /* }}} */
 1807: 
 1808: /* {{{ proto SNMP SNMP::__construct(int version, string hostname, string community|securityName [, long timeout [, long retries]])
 1809: 	Creates a new SNMP session to specified host. */
 1810: PHP_METHOD(snmp, __construct)
 1811: {
 1812: 	php_snmp_object *snmp_object;
 1813: 	zval *object = getThis();
 1814: 	char *a1, *a2;
 1815: 	int a1_len, a2_len;
 1816: 	long timeout = SNMP_DEFAULT_TIMEOUT;
 1817: 	long retries = SNMP_DEFAULT_RETRIES;
 1818: 	long version = SNMP_DEFAULT_VERSION;
 1819: 	int argc = ZEND_NUM_ARGS();
 1820: 	zend_error_handling error_handling;
 1821: 
 1822: 	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1823: 	zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
 1824: 	
 1825: 	if (zend_parse_parameters(argc TSRMLS_CC, "lss|ll", &version, &a1, &a1_len, &a2, &a2_len, &timeout, &retries) == FAILURE) {
 1826: 		zend_restore_error_handling(&error_handling TSRMLS_CC);
 1827: 		return;
 1828: 	}
 1829: 
 1830: 	zend_restore_error_handling(&error_handling TSRMLS_CC);
 1831: 
 1832: 	switch(version) {
 1833: 		case SNMP_VERSION_1:
 1834: 		case SNMP_VERSION_2c:
 1835: 		case SNMP_VERSION_3:
 1836: 			break;
 1837: 		default:
 1838: 			zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Unknown SNMP protocol version", 0 TSRMLS_CC);
 1839: 			return;
 1840: 	}
 1841: 
 1842: 	/* handle re-open of snmp session */
 1843: 	if (snmp_object->session) {
 1844: 		netsnmp_session_free(&(snmp_object->session));
 1845: 	}
 1846: 	
 1847: 	if (netsnmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries TSRMLS_CC)) {
 1848: 		return;
 1849: 	}
 1850: 	snmp_object->max_oids = 0;
 1851: 	snmp_object->valueretrieval = SNMP_G(valueretrieval);
 1852: 	snmp_object->enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
 1853: 	snmp_object->oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 1854: 	snmp_object->quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
 1855: 	snmp_object->oid_increasing_check = TRUE;
 1856: 	snmp_object->exceptions_enabled = 0;
 1857: }
 1858: /* }}} */
 1859: 
 1860: /* {{{ proto bool SNMP::close() 
 1861: 	Close SNMP session */
 1862: PHP_METHOD(snmp, close)
 1863: {
 1864: 	php_snmp_object *snmp_object;
 1865: 	zval *object = getThis();
 1866: 
 1867: 	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1868: 
 1869: 	if (zend_parse_parameters_none() == FAILURE) {
 1870: 		RETURN_FALSE;
 1871: 	}
 1872: 
 1873: 	netsnmp_session_free(&(snmp_object->session));
 1874: 
 1875: 	RETURN_TRUE;
 1876: }
 1877: /* }}} */
 1878: 
 1879: /* {{{ proto mixed SNMP::get(mixed object_id [, bool preserve_keys])
 1880:    Fetch a SNMP object returning scalar for single OID and array of oid->value pairs for multi OID request */
 1881: PHP_METHOD(snmp, get)
 1882: {
 1883: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, (-1));
 1884: }
 1885: /* }}} */
 1886: 
 1887: /* {{{ proto mixed SNMP::getnext(mixed object_id)
 1888:    Fetch a SNMP object returning scalar for single OID and array of oid->value pairs for multi OID request */
 1889: PHP_METHOD(snmp, getnext)
 1890: {
 1891: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, (-1));
 1892: }
 1893: /* }}} */
 1894: 
 1895: /* {{{ proto mixed SNMP::walk(mixed object_id [, bool $suffix_as_key = FALSE [, int $max_repetitions [, int $non_repeaters]])
 1896:    Return all objects including their respective object id withing the specified one as array of oid->value pairs */
 1897: PHP_METHOD(snmp, walk)
 1898: {
 1899: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, (-1));
 1900: }
 1901: /* }}} */
 1902: 
 1903: /* {{{ proto bool SNMP::set(mixed object_id, mixed type, mixed value) 
 1904:    Set the value of a SNMP object */
 1905: PHP_METHOD(snmp, set)
 1906: {
 1907: 	php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, (-1));
 1908: }
 1909: 
 1910: /* {{{ proto bool SNMP::setSecurity(string sec_level, [ string auth_protocol, string auth_passphrase [, string priv_protocol, string priv_passphrase [, string contextName [, string contextEngineID]]]])
 1911: 	Set SNMPv3 security-related session parameters */
 1912: PHP_METHOD(snmp, setSecurity)
 1913: {
 1914: 	php_snmp_object *snmp_object;
 1915: 	zval *object = getThis();
 1916: 	char *a1 = "", *a2 = "", *a3 = "", *a4 = "", *a5 = "", *a6 = "", *a7 = "";
 1917: 	int a1_len = 0, a2_len = 0, a3_len = 0, a4_len = 0, a5_len = 0, a6_len = 0, a7_len = 0;
 1918: 	int argc = ZEND_NUM_ARGS();
 1919: 
 1920: 	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1921: 	
 1922: 	if (zend_parse_parameters(argc TSRMLS_CC, "s|ssssss", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
 1923: 		&a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len) == FAILURE) {
 1924: 		RETURN_FALSE;
 1925: 	}
 1926: 
 1927: 	if (netsnmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7 TSRMLS_CC)) {
 1928: 		/* Warning message sent already, just bail out */
 1929: 		RETURN_FALSE;
 1930: 	}
 1931: 	RETURN_TRUE;
 1932: }
 1933: /* }}} */
 1934: 
 1935: /* {{{ proto long SNMP::getErrno() 
 1936: 	Get last error code number */
 1937: PHP_METHOD(snmp, getErrno)
 1938: {
 1939: 	php_snmp_object *snmp_object;
 1940: 	zval *object = getThis();
 1941: 
 1942: 	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1943: 
 1944: 	RETVAL_LONG(snmp_object->snmp_errno);
 1945: 	return;
 1946: }
 1947: /* }}} */
 1948: 
 1949: /* {{{ proto long SNMP::getError() 
 1950: 	Get last error message */
 1951: PHP_METHOD(snmp, getError)
 1952: {
 1953: 	php_snmp_object *snmp_object;
 1954: 	zval *object = getThis();
 1955: 
 1956: 	snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
 1957: 
 1958: 	RETVAL_STRING(snmp_object->snmp_errstr, 1);
 1959: 	return;
 1960: }
 1961: /* }}} */
 1962: 
 1963: /* {{{ */
 1964: 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)
 1965: {
 1966: 	php_snmp_prop_handler p;
 1967: 
 1968: 	p.name = (char*) name;
 1969: 	p.name_length = name_length;
 1970: 	p.read_func = (read_func) ? read_func : NULL;
 1971: 	p.write_func = (write_func) ? write_func : NULL;
 1972: 	zend_hash_add(h, (char *)name, name_length + 1, &p, sizeof(php_snmp_prop_handler), NULL);
 1973: }
 1974: /* }}} */
 1975: 
 1976: /* {{{ php_snmp_read_property(zval *object, zval *member, int type[, const zend_literal *key])
 1977:    Generic object property reader */
 1978: zval *php_snmp_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
 1979: {
 1980: 	zval tmp_member;
 1981: 	zval *retval;
 1982: 	php_snmp_object *obj;
 1983: 	php_snmp_prop_handler *hnd;
 1984: 	int ret;
 1985: 
 1986: 	ret = FAILURE;
 1987: 	obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
 1988: 
 1989: 	if (Z_TYPE_P(member) != IS_STRING) {
 1990: 		tmp_member = *member;
 1991: 		zval_copy_ctor(&tmp_member);
 1992: 		convert_to_string(&tmp_member);
 1993: 		member = &tmp_member;
 1994: 	}
 1995: 
 1996: 	ret = zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
 1997: 
 1998: 	if (ret == SUCCESS && hnd->read_func) {
 1999: 		ret = hnd->read_func(obj, &retval TSRMLS_CC);
 2000: 		if (ret == SUCCESS) {
 2001: 			/* ensure we're creating a temporary variable */
 2002: 			Z_SET_REFCOUNT_P(retval, 0);
 2003: 		} else {
 2004: 			retval = EG(uninitialized_zval_ptr);
 2005: 		}
 2006: 	} else {
 2007: 		zend_object_handlers * std_hnd = zend_get_std_object_handlers();
 2008: 		retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
 2009: 	}
 2010: 
 2011: 	if (member == &tmp_member) {
 2012: 		zval_dtor(member);
 2013: 	}
 2014: 	return(retval);
 2015: }
 2016: /* }}} */
 2017: 
 2018: /* {{{ php_snmp_write_property(zval *object, zval *member, zval *value[, const zend_literal *key])
 2019:    Generic object property writer */
 2020: void php_snmp_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
 2021: {
 2022: 	zval tmp_member;
 2023: 	php_snmp_object *obj;
 2024: 	php_snmp_prop_handler *hnd;
 2025: 	int ret;
 2026: 
 2027: 	if (Z_TYPE_P(member) != IS_STRING) {
 2028: 		tmp_member = *member;
 2029: 		zval_copy_ctor(&tmp_member);
 2030: 		convert_to_string(&tmp_member);
 2031: 		member = &tmp_member;
 2032: 	}
 2033: 
 2034: 	ret = FAILURE;
 2035: 	obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
 2036: 
 2037: 	ret = zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **) &hnd);
 2038: 
 2039: 	if (ret == SUCCESS && hnd->write_func) {
 2040: 		hnd->write_func(obj, value TSRMLS_CC);
 2041: 		if (! PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) == 0) {
 2042: 			Z_ADDREF_P(value);
 2043: 			zval_ptr_dtor(&value);
 2044: 		}
 2045: 	} else {
 2046: 		zend_object_handlers * std_hnd = zend_get_std_object_handlers();
 2047: 		std_hnd->write_property(object, member, value, key TSRMLS_CC);
 2048: 	}
 2049: 
 2050: 	if (member == &tmp_member) {
 2051: 		zval_dtor(member);
 2052: 	}
 2053: }
 2054: /* }}} */
 2055: 
 2056: /* {{{ php_snmp_has_property(zval *object, zval *member, int has_set_exists[, const zend_literal *key])
 2057:    Generic object property checker */
 2058: static int php_snmp_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC)
 2059: {
 2060: 	php_snmp_prop_handler *hnd;
 2061: 	int ret = 0;
 2062: 
 2063: 	if (zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **)&hnd) == SUCCESS) {
 2064: 		switch (has_set_exists) {
 2065: 			case 2:
 2066: 				ret = 1;
 2067: 				break;
 2068: 			case 0: {
 2069: 				zval *value = php_snmp_read_property(object, member, BP_VAR_IS, key TSRMLS_CC);
 2070: 				if (value != EG(uninitialized_zval_ptr)) {
 2071: 					ret = Z_TYPE_P(value) != IS_NULL? 1:0;
 2072: 					/* refcount is 0 */
 2073: 					Z_ADDREF_P(value);
 2074: 					zval_ptr_dtor(&value);
 2075: 				}
 2076: 				break;
 2077: 			}
 2078: 			default: {
 2079: 				zval *value = php_snmp_read_property(object, member, BP_VAR_IS, key TSRMLS_CC);
 2080: 				if (value != EG(uninitialized_zval_ptr)) {
 2081: 					convert_to_boolean(value);
 2082: 					ret = Z_BVAL_P(value)? 1:0;
 2083: 					/* refcount is 0 */
 2084: 					Z_ADDREF_P(value);
 2085: 					zval_ptr_dtor(&value);
 2086: 				}
 2087: 				break;
 2088: 			}
 2089: 		}
 2090: 	} else {
 2091: 		zend_object_handlers * std_hnd = zend_get_std_object_handlers();
 2092: 		ret = std_hnd->has_property(object, member, has_set_exists, key TSRMLS_CC);
 2093: 	}
 2094: 	return ret;
 2095: }
 2096: /* }}} */
 2097: 
 2098: /* {{{ php_snmp_get_properties(zval *object)
 2099:    Returns all object properties. Injects SNMP properties into object on first call */
 2100: static HashTable *php_snmp_get_properties(zval *object TSRMLS_DC)
 2101: {
 2102: 	php_snmp_object *obj;
 2103: 	php_snmp_prop_handler *hnd;
 2104: 	HashTable *props;
 2105: 	zval *val;
 2106: 	char *key;
 2107: 	uint key_len;
 2108: 	HashPosition pos;
 2109: 	ulong num_key;
 2110: 
 2111: 	obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
 2112: 	props = zend_std_get_properties(object TSRMLS_CC);
 2113: 
 2114: 	zend_hash_internal_pointer_reset_ex(&php_snmp_properties, &pos);
 2115: 
 2116: 	while (zend_hash_get_current_data_ex(&php_snmp_properties, (void**)&hnd, &pos) == SUCCESS) {
 2117: 		zend_hash_get_current_key_ex(&php_snmp_properties, &key, &key_len, &num_key, 0, &pos);
 2118: 		if (!hnd->read_func || hnd->read_func(obj, &val TSRMLS_CC) != SUCCESS) {
 2119: 			val = EG(uninitialized_zval_ptr);
 2120: 			Z_ADDREF_P(val);
 2121: 		}
 2122: 		zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
 2123: 		zend_hash_move_forward_ex(&php_snmp_properties, &pos);
 2124: 	}
 2125: 	return obj->zo.properties;
 2126: }
 2127: /* }}} */
 2128: 
 2129: /* {{{ */
 2130: static int php_snmp_read_info(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
 2131: {
 2132: 	zval *val;
 2133: 
 2134: 	MAKE_STD_ZVAL(*retval);
 2135: 	array_init(*retval);
 2136: 
 2137: 	if (snmp_object->session == NULL) {
 2138: 		return SUCCESS;
 2139: 	}
 2140: 		
 2141: 	MAKE_STD_ZVAL(val);
 2142: 	ZVAL_STRINGL(val, snmp_object->session->peername, strlen(snmp_object->session->peername), 1);
 2143: 	add_assoc_zval(*retval, "hostname", val);
 2144: 	
 2145: 	MAKE_STD_ZVAL(val);
 2146: 	ZVAL_LONG(val, snmp_object->session->remote_port);
 2147: 	add_assoc_zval(*retval, "port", val);
 2148: 	
 2149: 	MAKE_STD_ZVAL(val);
 2150: 	ZVAL_LONG(val, snmp_object->session->timeout);
 2151: 	add_assoc_zval(*retval, "timeout", val);
 2152: 	
 2153: 	MAKE_STD_ZVAL(val);
 2154: 	ZVAL_LONG(val, snmp_object->session->retries);
 2155: 	add_assoc_zval(*retval, "retries", val);
 2156: 	
 2157: 	return SUCCESS;
 2158: }
 2159: /* }}} */
 2160: 
 2161: /* {{{ */
 2162: static int php_snmp_read_max_oids(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
 2163: {
 2164: 	MAKE_STD_ZVAL(*retval);
 2165: 	if (snmp_object->max_oids > 0) {
 2166: 		ZVAL_LONG(*retval, snmp_object->max_oids);
 2167: 	} else {
 2168: 		ZVAL_NULL(*retval);
 2169: 	}
 2170: 	return SUCCESS;
 2171: }
 2172: /* }}} */
 2173: 
 2174: #define PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(name) \
 2175: 	static int php_snmp_read_##name(php_snmp_object *snmp_object, zval **retval TSRMLS_DC) \
 2176: 	{ \
 2177: 		MAKE_STD_ZVAL(*retval); \
 2178: 		ZVAL_BOOL(*retval, snmp_object->name); \
 2179: 		return SUCCESS; \
 2180: 	}
 2181: 
 2182: PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(oid_increasing_check)
 2183: PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(quick_print)
 2184: PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(enum_print)
 2185: 
 2186: #define PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(name) \
 2187: 	static int php_snmp_read_##name(php_snmp_object *snmp_object, zval **retval TSRMLS_DC) \
 2188: 	{ \
 2189: 		MAKE_STD_ZVAL(*retval); \
 2190: 		ZVAL_LONG(*retval, snmp_object->name); \
 2191: 		return SUCCESS; \
 2192: 	}
 2193: 
 2194: PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(valueretrieval)
 2195: PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(oid_output_format)
 2196: PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(exceptions_enabled)
 2197: 
 2198: /* {{{ */
 2199: static int php_snmp_write_info(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 2200: {
 2201: 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "info property is read-only");
 2202: 	return FAILURE;
 2203: }
 2204: /* }}} */
 2205: 
 2206: /* {{{ */
 2207: static int php_snmp_write_max_oids(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 2208: {
 2209: 	zval ztmp;
 2210: 	int ret = SUCCESS;
 2211: 
 2212: 	if (Z_TYPE_P(newval) == IS_NULL) {
 2213: 		snmp_object->max_oids = 0;
 2214: 		return ret;
 2215: 	}
 2216: 
 2217: 	if (Z_TYPE_P(newval) != IS_LONG) {
 2218: 		ztmp = *newval;
 2219: 		zval_copy_ctor(&ztmp);
 2220: 		convert_to_long(&ztmp);
 2221: 		newval = &ztmp;
 2222: 	}
 2223: 
 2224: 	if (Z_LVAL_P(newval) > 0) {
 2225: 		snmp_object->max_oids = Z_LVAL_P(newval);
 2226: 	} else {
 2227: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "max_oids should be positive integer or NULL, got %ld", Z_LVAL_P(newval));
 2228: 	}
 2229: 	
 2230: 	if (newval == &ztmp) {
 2231: 		zval_dtor(newval);
 2232: 	}
 2233: 
 2234: 	return ret;
 2235: }
 2236: /* }}} */
 2237: 
 2238: /* {{{ */
 2239: static int php_snmp_write_valueretrieval(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 2240: {
 2241: 	zval ztmp;
 2242: 	int ret = SUCCESS;
 2243: 
 2244: 	if (Z_TYPE_P(newval) != IS_LONG) {
 2245: 		ztmp = *newval;
 2246: 		zval_copy_ctor(&ztmp);
 2247: 		convert_to_long(&ztmp);
 2248: 		newval = &ztmp;
 2249: 	}
 2250: 
 2251: 	if (Z_LVAL_P(newval) >= 0 && Z_LVAL_P(newval) <= (SNMP_VALUE_LIBRARY|SNMP_VALUE_PLAIN|SNMP_VALUE_OBJECT)) {
 2252: 		snmp_object->valueretrieval = Z_LVAL_P(newval);
 2253: 	} else {
 2254: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP value retrieval method '%ld'", Z_LVAL_P(newval));
 2255: 		ret = FAILURE;
 2256: 	}
 2257: 	
 2258: 	if (newval == &ztmp) {
 2259: 		zval_dtor(newval);
 2260: 	}
 2261: 
 2262: 	return ret;
 2263: }
 2264: /* }}} */
 2265: 
 2266: #define PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(name) \
 2267: static int php_snmp_write_##name(php_snmp_object *snmp_object, zval *newval TSRMLS_DC) \
 2268: { \
 2269: 	zval ztmp; \
 2270: 	if (Z_TYPE_P(newval) != IS_BOOL) { \
 2271: 		ztmp = *newval; \
 2272: 		zval_copy_ctor(&ztmp); \
 2273: 		convert_to_boolean(&ztmp); \
 2274: 		newval = &ztmp; \
 2275: 	} \
 2276: \
 2277: 	snmp_object->name = Z_LVAL_P(newval); \
 2278: \
 2279: 	if (newval == &ztmp) { \
 2280: 		zval_dtor(newval); \
 2281: 	} \
 2282: 	return SUCCESS; \
 2283: }
 2284: 
 2285: PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(quick_print)
 2286: PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(enum_print)
 2287: PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(oid_increasing_check)
 2288: 
 2289: /* {{{ */
 2290: static int php_snmp_write_oid_output_format(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 2291: {
 2292: 	zval ztmp;
 2293: 	int ret = SUCCESS;
 2294: 	if (Z_TYPE_P(newval) != IS_LONG) {
 2295: 		ztmp = *newval;
 2296: 		zval_copy_ctor(&ztmp);
 2297: 		convert_to_long(&ztmp);
 2298: 		newval = &ztmp;
 2299: 	}
 2300: 	
 2301: 	switch(Z_LVAL_P(newval)) {
 2302: 		case NETSNMP_OID_OUTPUT_SUFFIX:
 2303: 		case NETSNMP_OID_OUTPUT_MODULE:
 2304: 		case NETSNMP_OID_OUTPUT_FULL:
 2305: 		case NETSNMP_OID_OUTPUT_NUMERIC:
 2306: 		case NETSNMP_OID_OUTPUT_UCD:
 2307: 		case NETSNMP_OID_OUTPUT_NONE:
 2308: 			snmp_object->oid_output_format = Z_LVAL_P(newval);
 2309: 			break;
 2310: 		default:
 2311: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP output print format '%ld'", Z_LVAL_P(newval));
 2312: 			ret = FAILURE;
 2313: 			break;
 2314: 	}
 2315: 
 2316: 	if (newval == &ztmp) {
 2317: 		zval_dtor(newval);
 2318: 	}
 2319: 	return ret;
 2320: }
 2321: /* }}} */
 2322: 
 2323: /* {{{ */
 2324: static int php_snmp_write_exceptions_enabled(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
 2325: {
 2326: 	zval ztmp;
 2327: 	int ret = SUCCESS;
 2328: 	if (Z_TYPE_P(newval) != IS_LONG) {
 2329: 		ztmp = *newval;
 2330: 		zval_copy_ctor(&ztmp);
 2331: 		convert_to_long(&ztmp);
 2332: 		newval = &ztmp;
 2333: 	}
 2334: 
 2335: 	snmp_object->exceptions_enabled = Z_LVAL_P(newval);	
 2336: 
 2337: 	if (newval == &ztmp) {
 2338: 		zval_dtor(newval);
 2339: 	}
 2340: 	return ret;
 2341: }
 2342: /* }}} */
 2343: 
 2344: /* {{{ php_snmp_class_methods[] */
 2345: static zend_function_entry php_snmp_class_methods[] = {
 2346: 	PHP_ME(snmp,	 __construct,			arginfo_snmp_create,		ZEND_ACC_PUBLIC)
 2347: 	PHP_ME(snmp,	 close,				arginfo_snmp_void,		ZEND_ACC_PUBLIC)
 2348: 	PHP_ME(snmp,	 setSecurity,			arginfo_snmp_setSecurity,	ZEND_ACC_PUBLIC)
 2349: 
 2350: 	PHP_ME(snmp,	 get,				arginfo_snmp_get,		ZEND_ACC_PUBLIC)
 2351: 	PHP_ME(snmp,	 getnext,			arginfo_snmp_get,		ZEND_ACC_PUBLIC)
 2352: 	PHP_ME(snmp,	 walk,				arginfo_snmp_walk,		ZEND_ACC_PUBLIC)
 2353: 	PHP_ME(snmp,	 set,				arginfo_snmp_set,		ZEND_ACC_PUBLIC)
 2354: 	PHP_ME(snmp,	 getErrno,			arginfo_snmp_void,		ZEND_ACC_PUBLIC)
 2355: 	PHP_ME(snmp,	 getError,			arginfo_snmp_void,		ZEND_ACC_PUBLIC)
 2356: 
 2357: 	PHP_FE_END
 2358: };
 2359: 
 2360: #define PHP_SNMP_PROPERTY_ENTRY_RECORD(name) \
 2361: 	{ "" #name "",		sizeof("" #name "") - 1,	php_snmp_read_##name,	php_snmp_write_##name }
 2362: 
 2363: const php_snmp_prop_handler php_snmp_property_entries[] = {
 2364: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(info),
 2365: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(max_oids),
 2366: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(valueretrieval),
 2367: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(quick_print),
 2368: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(enum_print),
 2369: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(oid_output_format),
 2370: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(oid_increasing_check),
 2371: 	PHP_SNMP_PROPERTY_ENTRY_RECORD(exceptions_enabled),
 2372: 	{ NULL, 0, NULL, NULL}
 2373: };
 2374: /* }}} */
 2375: 
 2376: /* {{{ PHP_MINIT_FUNCTION
 2377:  */
 2378: PHP_MINIT_FUNCTION(snmp)
 2379: {
 2380: 	netsnmp_log_handler *logh;
 2381: 	zend_class_entry ce, cex;
 2382: 
 2383: 	le_snmp_session = zend_register_list_destructors_ex(php_snmp_session_destructor, NULL, PHP_SNMP_SESSION_RES_NAME, module_number);
 2384: 
 2385: 	init_snmp("snmpapp");
 2386: 
 2387: #ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
 2388: 	/* Prevent update of the snmpapp.conf file */
 2389: 	netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
 2390: #endif
 2391: 
 2392: 	/* Disable logging, use exit status'es and related variabled to detect errors */
 2393: 	shutdown_snmp_logging();
 2394: 	logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_NONE, LOG_ERR);
 2395: 	if (logh) {
 2396: 		logh->pri_max = LOG_ERR;
 2397: 	}
 2398: 
 2399: 	memcpy(&php_snmp_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
 2400: 	php_snmp_object_handlers.read_property = php_snmp_read_property;
 2401: 	php_snmp_object_handlers.write_property = php_snmp_write_property;
 2402: 	php_snmp_object_handlers.has_property = php_snmp_has_property;
 2403: 	php_snmp_object_handlers.get_properties = php_snmp_get_properties;
 2404: 
 2405: 	/* Register SNMP Class */
 2406: 	INIT_CLASS_ENTRY(ce, "SNMP", php_snmp_class_methods);
 2407: 	ce.create_object = php_snmp_object_new;
 2408: 	php_snmp_object_handlers.clone_obj = NULL;
 2409: 	php_snmp_ce = zend_register_internal_class(&ce TSRMLS_CC);
 2410: 
 2411: 	/* Register SNMP Class properties */
 2412: 	zend_hash_init(&php_snmp_properties, 0, NULL, NULL, 1);
 2413: 	PHP_SNMP_ADD_PROPERTIES(&php_snmp_properties, php_snmp_property_entries);
 2414: 
 2415: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_SUFFIX",	NETSNMP_OID_OUTPUT_SUFFIX,	CONST_CS | CONST_PERSISTENT);
 2416: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_MODULE",	NETSNMP_OID_OUTPUT_MODULE,	CONST_CS | CONST_PERSISTENT);
 2417: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_FULL",		NETSNMP_OID_OUTPUT_FULL,	CONST_CS | CONST_PERSISTENT);
 2418: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NUMERIC",	NETSNMP_OID_OUTPUT_NUMERIC,	CONST_CS | CONST_PERSISTENT);
 2419: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_UCD",		NETSNMP_OID_OUTPUT_UCD,		CONST_CS | CONST_PERSISTENT);
 2420: 	REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NONE",		NETSNMP_OID_OUTPUT_NONE,	CONST_CS | CONST_PERSISTENT);
 2421: 
 2422: 	REGISTER_LONG_CONSTANT("SNMP_VALUE_LIBRARY",	SNMP_VALUE_LIBRARY,	CONST_CS | CONST_PERSISTENT);
 2423: 	REGISTER_LONG_CONSTANT("SNMP_VALUE_PLAIN",	SNMP_VALUE_PLAIN,	CONST_CS | CONST_PERSISTENT);
 2424: 	REGISTER_LONG_CONSTANT("SNMP_VALUE_OBJECT",	SNMP_VALUE_OBJECT,	CONST_CS | CONST_PERSISTENT);
 2425: 
 2426: 	REGISTER_LONG_CONSTANT("SNMP_BIT_STR",		ASN_BIT_STR,	CONST_CS | CONST_PERSISTENT);
 2427: 	REGISTER_LONG_CONSTANT("SNMP_OCTET_STR",	ASN_OCTET_STR,	CONST_CS | CONST_PERSISTENT);
 2428: 	REGISTER_LONG_CONSTANT("SNMP_OPAQUE",		ASN_OPAQUE,	CONST_CS | CONST_PERSISTENT);
 2429: 	REGISTER_LONG_CONSTANT("SNMP_NULL",		ASN_NULL,	CONST_CS | CONST_PERSISTENT);
 2430: 	REGISTER_LONG_CONSTANT("SNMP_OBJECT_ID",	ASN_OBJECT_ID,	CONST_CS | CONST_PERSISTENT);
 2431: 	REGISTER_LONG_CONSTANT("SNMP_IPADDRESS",	ASN_IPADDRESS,	CONST_CS | CONST_PERSISTENT);
 2432: 	REGISTER_LONG_CONSTANT("SNMP_COUNTER",		ASN_GAUGE,	CONST_CS | CONST_PERSISTENT);
 2433: 	REGISTER_LONG_CONSTANT("SNMP_UNSIGNED",		ASN_UNSIGNED,	CONST_CS | CONST_PERSISTENT);
 2434: 	REGISTER_LONG_CONSTANT("SNMP_TIMETICKS",	ASN_TIMETICKS,	CONST_CS | CONST_PERSISTENT);
 2435: 	REGISTER_LONG_CONSTANT("SNMP_UINTEGER",		ASN_UINTEGER,	CONST_CS | CONST_PERSISTENT);
 2436: 	REGISTER_LONG_CONSTANT("SNMP_INTEGER",		ASN_INTEGER,	CONST_CS | CONST_PERSISTENT);
 2437: 	REGISTER_LONG_CONSTANT("SNMP_COUNTER64",	ASN_COUNTER64,	CONST_CS | CONST_PERSISTENT);
 2438: 
 2439: 	REGISTER_SNMP_CLASS_CONST_LONG("VERSION_1",			SNMP_VERSION_1);
 2440: 	REGISTER_SNMP_CLASS_CONST_LONG("VERSION_2c",			SNMP_VERSION_2c);
 2441: 	REGISTER_SNMP_CLASS_CONST_LONG("VERSION_2C",			SNMP_VERSION_2c);
 2442: 	REGISTER_SNMP_CLASS_CONST_LONG("VERSION_3",			SNMP_VERSION_3);
 2443: 
 2444: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_NOERROR",			PHP_SNMP_ERRNO_NOERROR);
 2445: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_ANY",			PHP_SNMP_ERRNO_ANY);
 2446: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_GENERIC",			PHP_SNMP_ERRNO_GENERIC);
 2447: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_TIMEOUT",			PHP_SNMP_ERRNO_TIMEOUT);
 2448: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_ERROR_IN_REPLY",		PHP_SNMP_ERRNO_ERROR_IN_REPLY);
 2449: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_OID_NOT_INCREASING",	PHP_SNMP_ERRNO_OID_NOT_INCREASING);
 2450: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_OID_PARSING_ERROR",	PHP_SNMP_ERRNO_OID_PARSING_ERROR);
 2451: 	REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_MULTIPLE_SET_QUERIES",	PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES);
 2452: 
 2453: 	/* Register SNMPException class */
 2454: 	INIT_CLASS_ENTRY(cex, "SNMPException", NULL);
 2455: #ifdef HAVE_SPL
 2456: 	php_snmp_exception_ce = zend_register_internal_class_ex(&cex, spl_ce_RuntimeException, NULL TSRMLS_CC);
 2457: #else
 2458: 	php_snmp_exception_ce = zend_register_internal_class_ex(&cex, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
 2459: #endif
 2460: 
 2461: 	return SUCCESS;
 2462: }
 2463: /* }}} */
 2464: 
 2465: /* {{{ PHP_MSHUTDOWN_FUNCTION
 2466:  */
 2467: PHP_MSHUTDOWN_FUNCTION(snmp)
 2468: {
 2469: 	snmp_shutdown("snmpapp");
 2470: 	
 2471: 	zend_hash_destroy(&php_snmp_properties);
 2472: 
 2473: 	return SUCCESS;
 2474: }
 2475: /* }}} */
 2476: 
 2477: /* {{{ PHP_MINFO_FUNCTION
 2478:  */
 2479: PHP_MINFO_FUNCTION(snmp)
 2480: {
 2481: 	php_info_print_table_start();
 2482: 	php_info_print_table_row(2, "NET-SNMP Support", "enabled");
 2483: 	php_info_print_table_row(2, "NET-SNMP Version", netsnmp_get_version());
 2484: 	php_info_print_table_row(2, "PHP SNMP Version", PHP_SNMP_VERSION);
 2485: 	php_info_print_table_end();
 2486: }
 2487: /* }}} */
 2488: 
 2489: /* {{{ snmp_module_deps[]
 2490:  */
 2491: static const zend_module_dep snmp_module_deps[] = {
 2492: #ifdef HAVE_SPL
 2493: 	ZEND_MOD_REQUIRED("spl")
 2494: #endif
 2495: 	ZEND_MOD_END
 2496: };
 2497: /* }}} */
 2498: 
 2499: /* {{{ snmp_module_entry
 2500:  */
 2501: zend_module_entry snmp_module_entry = {
 2502: 	STANDARD_MODULE_HEADER_EX,
 2503: 	NULL,
 2504: 	snmp_module_deps,
 2505: 	"snmp",
 2506: 	snmp_functions,
 2507: 	PHP_MINIT(snmp),
 2508: 	PHP_MSHUTDOWN(snmp),
 2509: 	NULL,
 2510: 	NULL,
 2511: 	PHP_MINFO(snmp),
 2512: 	PHP_SNMP_VERSION,
 2513: 	PHP_MODULE_GLOBALS(snmp),
 2514: 	PHP_GINIT(snmp),
 2515: 	NULL,
 2516: 	NULL,
 2517: 	STANDARD_MODULE_PROPERTIES_EX
 2518: };
 2519: /* }}} */
 2520: 
 2521: #endif
 2522: 
 2523: /*
 2524:  * Local variables:
 2525:  * tab-width: 4
 2526:  * c-basic-offset: 4
 2527:  * End:
 2528:  * vim600: sw=4 ts=4 fdm=marker
 2529:  * vim<600: sw=4 ts=4
 2530:  */

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