Annotation of embedaddon/php/ext/snmp/snmp.c, revision 1.1.1.2

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

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