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

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

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