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

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2012 The PHP Group                                |
                      6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
                     16:    |          Mike Jackson <mhjack@tscnet.com>                            |
                     17:    |          Steven Lawrance <slawrance@technologist.com>                |
                     18:    |          Harrie Hazewinkel <harrie@lisanza.net>                      |
                     19:    |          Johann Hanne <jonny@nurfuerspam.de>                         |
                     20:    +----------------------------------------------------------------------+
                     21:  */
                     22: 
                     23: /* $Id: snmp.c 321634 2012-01-01 13:15:04Z felipe $ */
                     24: 
                     25: #ifdef HAVE_CONFIG_H
                     26: #include "config.h"
                     27: #endif
                     28: 
                     29: #include "php.h"
                     30: #include "ext/standard/info.h"
                     31: #include "php_snmp.h"
                     32: 
                     33: #if HAVE_SNMP
                     34: 
                     35: #include <sys/types.h>
                     36: #ifdef PHP_WIN32
                     37: #include <winsock2.h>
                     38: #include <errno.h>
                     39: #include <process.h>
                     40: #include "win32/time.h"
                     41: #elif defined(NETWARE)
                     42: #ifdef USE_WINSOCK
                     43: #include <novsock2.h>
                     44: #else
                     45: #include <sys/socket.h>
                     46: #endif
                     47: #include <errno.h>
                     48: #include <sys/timeval.h>
                     49: #else
                     50: #include <sys/socket.h>
                     51: #include <netinet/in.h>
                     52: #include <arpa/inet.h>
                     53: #ifndef _OSD_POSIX
                     54: #include <sys/errno.h>
                     55: #else
                     56: #include <errno.h>  /* BS2000/OSD uses <errno.h>, not <sys/errno.h> */
                     57: #endif
                     58: #include <netdb.h>
                     59: #endif
                     60: #ifdef HAVE_UNISTD_H
                     61: #include <unistd.h>
                     62: #endif
                     63: 
                     64: #ifndef __P
                     65: #ifdef __GNUC__
                     66: #define __P(args) args
                     67: #else
                     68: #define __P(args) ()
                     69: #endif
                     70: #endif
                     71: 
                     72: #ifdef HAVE_NET_SNMP
                     73: #include <net-snmp/net-snmp-config.h>
                     74: #include <net-snmp/net-snmp-includes.h>
                     75: #else
                     76: #ifdef HAVE_DEFAULT_STORE_H
                     77: #include "default_store.h"
                     78: #endif
                     79: #include "asn1.h"
                     80: #include "snmp_api.h"
                     81: #include "snmp_client.h"
                     82: #include "snmp_impl.h"
                     83: #include "snmp.h"
                     84: #include "snmpv3.h"
                     85: #include "keytools.h"
                     86: #include "parse.h"
                     87: #include "mib.h"
                     88: #ifndef PHP_WIN32
                     89: /* this doesn't appear to be needed under win32 (perhaps at all)
                     90:  * and the header file is not present in my UCD-SNMP headers */
                     91: # include "version.h"
                     92: #endif
                     93: #include "transform_oids.h"
                     94: #endif
                     95: /* Ugly macro, since the length of OIDs in UCD-SNMP and NET-SNMP
                     96:  * is different and this way the code is not full of 'ifdef's.
                     97:  */
                     98: #define OIDSIZE(p) (sizeof(p)/sizeof(oid))
                     99: 
                    100: /* For really old ucd-snmp versions.. */
                    101: #ifndef HAVE_SNMP_PARSE_OID
                    102: #define snmp_parse_oid read_objid
                    103: #endif
                    104: 
                    105: #define SNMP_VALUE_LIBRARY     0
                    106: #define SNMP_VALUE_PLAIN       1
                    107: #define SNMP_VALUE_OBJECT      2
                    108: 
                    109: ZEND_DECLARE_MODULE_GLOBALS(snmp)
                    110: static PHP_GINIT_FUNCTION(snmp);
                    111: 
                    112: /* constant - can be shared among threads */
                    113: static oid objid_mib[] = {1, 3, 6, 1, 2, 1};
                    114: 
                    115: /* {{{ arginfo */
                    116: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpget, 0, 0, 3)
                    117:        ZEND_ARG_INFO(0, host)
                    118:        ZEND_ARG_INFO(0, community)
                    119:        ZEND_ARG_INFO(0, object_id)
                    120:        ZEND_ARG_INFO(0, timeout)
                    121:        ZEND_ARG_INFO(0, retries)
                    122: ZEND_END_ARG_INFO()
                    123: 
                    124: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpgetnext, 0, 0, 3)
                    125:        ZEND_ARG_INFO(0, host)
                    126:        ZEND_ARG_INFO(0, community)
                    127:        ZEND_ARG_INFO(0, object_id)
                    128:        ZEND_ARG_INFO(0, timeout)
                    129:        ZEND_ARG_INFO(0, retries)
                    130: ZEND_END_ARG_INFO()
                    131: 
                    132: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpwalk, 0, 0, 3)
                    133:        ZEND_ARG_INFO(0, host)
                    134:        ZEND_ARG_INFO(0, community)
                    135:        ZEND_ARG_INFO(0, object_id)
                    136:        ZEND_ARG_INFO(0, timeout)
                    137:        ZEND_ARG_INFO(0, retries)
                    138: ZEND_END_ARG_INFO()
                    139: 
                    140: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmprealwalk, 0, 0, 3)
                    141:        ZEND_ARG_INFO(0, host)
                    142:        ZEND_ARG_INFO(0, community)
                    143:        ZEND_ARG_INFO(0, object_id)
                    144:        ZEND_ARG_INFO(0, timeout)
                    145:        ZEND_ARG_INFO(0, retries)
                    146: ZEND_END_ARG_INFO()
                    147: 
                    148: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_get_quick_print, 0, 0, 1)
                    149:        ZEND_ARG_INFO(0, d)
                    150: ZEND_END_ARG_INFO()
                    151: 
                    152: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_quick_print, 0, 0, 1)
                    153:        ZEND_ARG_INFO(0, quick_print)
                    154: ZEND_END_ARG_INFO()
                    155: 
                    156: #ifdef HAVE_NET_SNMP
                    157: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_enum_print, 0, 0, 1)
                    158:        ZEND_ARG_INFO(0, enum_print)
                    159: ZEND_END_ARG_INFO()
                    160: 
                    161: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_oid_output_format, 0, 0, 1)
                    162:        ZEND_ARG_INFO(0, oid_format)
                    163: ZEND_END_ARG_INFO()
                    164: #endif
                    165: 
                    166: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpset, 0, 0, 5)
                    167:        ZEND_ARG_INFO(0, host)
                    168:        ZEND_ARG_INFO(0, community)
                    169:        ZEND_ARG_INFO(0, object_id)
                    170:        ZEND_ARG_INFO(0, type)
                    171:        ZEND_ARG_INFO(0, value)
                    172:        ZEND_ARG_INFO(0, timeout)
                    173:        ZEND_ARG_INFO(0, retries)
                    174: ZEND_END_ARG_INFO()
                    175: 
                    176: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_get, 0, 0, 3)
                    177:        ZEND_ARG_INFO(0, host)
                    178:        ZEND_ARG_INFO(0, community)
                    179:        ZEND_ARG_INFO(0, object_id)
                    180:        ZEND_ARG_INFO(0, timeout)
                    181:        ZEND_ARG_INFO(0, retries)
                    182: ZEND_END_ARG_INFO()
                    183: 
                    184: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_getnext, 0, 0, 3)
                    185:        ZEND_ARG_INFO(0, host)
                    186:        ZEND_ARG_INFO(0, community)
                    187:        ZEND_ARG_INFO(0, object_id)
                    188:        ZEND_ARG_INFO(0, timeout)
                    189:        ZEND_ARG_INFO(0, retries)
                    190: ZEND_END_ARG_INFO()
                    191: 
                    192: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_walk, 0, 0, 3)
                    193:        ZEND_ARG_INFO(0, host)
                    194:        ZEND_ARG_INFO(0, community)
                    195:        ZEND_ARG_INFO(0, object_id)
                    196:        ZEND_ARG_INFO(0, timeout)
                    197:        ZEND_ARG_INFO(0, retries)
                    198: ZEND_END_ARG_INFO()
                    199: 
                    200: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_real_walk, 0, 0, 3)
                    201:        ZEND_ARG_INFO(0, host)
                    202:        ZEND_ARG_INFO(0, community)
                    203:        ZEND_ARG_INFO(0, object_id)
                    204:        ZEND_ARG_INFO(0, timeout)
                    205:        ZEND_ARG_INFO(0, retries)
                    206: ZEND_END_ARG_INFO()
                    207: 
                    208: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_set, 0, 0, 5)
                    209:        ZEND_ARG_INFO(0, host)
                    210:        ZEND_ARG_INFO(0, community)
                    211:        ZEND_ARG_INFO(0, object_id)
                    212:        ZEND_ARG_INFO(0, type)
                    213:        ZEND_ARG_INFO(0, value)
                    214:        ZEND_ARG_INFO(0, timeout)
                    215:        ZEND_ARG_INFO(0, retries)
                    216: ZEND_END_ARG_INFO()
                    217: 
                    218: ZEND_BEGIN_ARG_INFO_EX(arginfo_php_snmpv3, 0, 0, 2)
                    219:        ZEND_ARG_INFO(0, s)
                    220:        ZEND_ARG_INFO(0, st)
                    221: ZEND_END_ARG_INFO()
                    222: 
                    223: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_get, 0, 0, 8)
                    224:        ZEND_ARG_INFO(0, host)
                    225:        ZEND_ARG_INFO(0, sec_name)
                    226:        ZEND_ARG_INFO(0, sec_level)
                    227:        ZEND_ARG_INFO(0, auth_protocol)
                    228:        ZEND_ARG_INFO(0, auth_passphrase)
                    229:        ZEND_ARG_INFO(0, priv_protocol)
                    230:        ZEND_ARG_INFO(0, priv_passphrase)
                    231:        ZEND_ARG_INFO(0, object_id)
                    232:        ZEND_ARG_INFO(0, timeout)
                    233:        ZEND_ARG_INFO(0, retries)
                    234: ZEND_END_ARG_INFO()
                    235: 
                    236: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_getnext, 0, 0, 8)
                    237:        ZEND_ARG_INFO(0, host)
                    238:        ZEND_ARG_INFO(0, sec_name)
                    239:        ZEND_ARG_INFO(0, sec_level)
                    240:        ZEND_ARG_INFO(0, auth_protocol)
                    241:        ZEND_ARG_INFO(0, auth_passphrase)
                    242:        ZEND_ARG_INFO(0, priv_protocol)
                    243:        ZEND_ARG_INFO(0, priv_passphrase)
                    244:        ZEND_ARG_INFO(0, object_id)
                    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_walk, 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_real_walk, 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_set, 0, 0, 10)
                    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, type)
                    285:        ZEND_ARG_INFO(0, value)
                    286:        ZEND_ARG_INFO(0, timeout)
                    287:        ZEND_ARG_INFO(0, retries)
                    288: ZEND_END_ARG_INFO()
                    289: 
                    290: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_valueretrieval, 0, 0, 1)
                    291:        ZEND_ARG_INFO(0, method)
                    292: ZEND_END_ARG_INFO()
                    293: 
                    294: ZEND_BEGIN_ARG_INFO(arginfo_snmp_get_valueretrieval, 0)
                    295: ZEND_END_ARG_INFO()
                    296: 
                    297: ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_read_mib, 0, 0, 1)
                    298:        ZEND_ARG_INFO(0, filename)
                    299: ZEND_END_ARG_INFO()
                    300: /* }}} */
                    301: 
                    302: /* {{{ snmp_functions[]
                    303:  */
                    304: const zend_function_entry snmp_functions[] = {
                    305:        PHP_FE(snmpget,                                                 arginfo_snmpget)
                    306:        PHP_FE(snmpgetnext,                                     arginfo_snmpgetnext)
                    307:        PHP_FE(snmpwalk,                                                arginfo_snmpwalk)
                    308:        PHP_FE(snmprealwalk,                                    arginfo_snmprealwalk)
                    309:        PHP_FALIAS(snmpwalkoid, snmprealwalk,   arginfo_snmprealwalk)
                    310:        PHP_FE(snmp_get_quick_print,                    arginfo_snmp_get_quick_print)
                    311:        PHP_FE(snmp_set_quick_print,                    arginfo_snmp_set_quick_print)
                    312: #ifdef HAVE_NET_SNMP
                    313:        PHP_FE(snmp_set_enum_print,                     arginfo_snmp_set_enum_print)
                    314:        PHP_FE(snmp_set_oid_output_format,              arginfo_snmp_set_oid_output_format)
                    315:        PHP_FALIAS(snmp_set_oid_numeric_print, snmp_set_oid_output_format, arginfo_snmp_set_oid_output_format)
                    316: #endif
                    317:        PHP_FE(snmpset,                                 arginfo_snmpset)
                    318: 
                    319:        PHP_FE(snmp2_get,                               arginfo_snmp2_get)
                    320:        PHP_FE(snmp2_getnext,                   arginfo_snmp2_getnext)
                    321:        PHP_FE(snmp2_walk,                              arginfo_snmp2_walk)
                    322:        PHP_FE(snmp2_real_walk,                 arginfo_snmp2_real_walk)
                    323:        PHP_FE(snmp2_set,                               arginfo_snmp2_set)
                    324: 
                    325:        PHP_FE(snmp3_get,                               arginfo_snmp3_get)
                    326:        PHP_FE(snmp3_getnext,                   arginfo_snmp3_getnext)
                    327:        PHP_FE(snmp3_walk,                              arginfo_snmp3_walk)
                    328:        PHP_FE(snmp3_real_walk,                 arginfo_snmp3_real_walk)
                    329:        PHP_FE(snmp3_set,                               arginfo_snmp3_set)
                    330:        PHP_FE(snmp_set_valueretrieval, arginfo_snmp_set_valueretrieval)
                    331:        PHP_FE(snmp_get_valueretrieval, arginfo_snmp_get_valueretrieval)
                    332: 
                    333:        PHP_FE(snmp_read_mib,                   arginfo_snmp_read_mib)
                    334:        PHP_FE_END
                    335: };
                    336: /* }}} */
                    337: 
                    338: #define SNMP_CMD_GET           1
                    339: #define SNMP_CMD_GETNEXT       2
                    340: #define SNMP_CMD_WALK          3
                    341: #define SNMP_CMD_REALWALK      4
                    342: #define SNMP_CMD_SET           11
                    343: 
                    344: /* {{{ snmp_module_entry
                    345:  */
                    346: zend_module_entry snmp_module_entry = {
                    347:        STANDARD_MODULE_HEADER,
                    348:        "snmp",
                    349:        snmp_functions,
                    350:        PHP_MINIT(snmp),
                    351:        PHP_MSHUTDOWN(snmp),
                    352:        NULL,
                    353:        NULL,
                    354:        PHP_MINFO(snmp),
                    355:        NO_VERSION_YET,
                    356:        PHP_MODULE_GLOBALS(snmp),
                    357:        PHP_GINIT(snmp),
                    358:        NULL,
                    359:        NULL,
                    360:        STANDARD_MODULE_PROPERTIES_EX
                    361: };
                    362: /* }}} */
                    363: 
                    364: #ifdef COMPILE_DL_SNMP
                    365: ZEND_GET_MODULE(snmp)
                    366: #endif
                    367: 
                    368: /* THREAD_LS snmp_module php_snmp_module; - may need one of these at some point */
                    369: 
                    370: /* {{{ PHP_GINIT_FUNCTION
                    371:  */
                    372: static PHP_GINIT_FUNCTION(snmp)
                    373: {
                    374:        snmp_globals->valueretrieval = SNMP_VALUE_LIBRARY;
                    375: }
                    376: /* }}} */
                    377: 
                    378: /* {{{ PHP_MINIT_FUNCTION
                    379:  */
                    380: PHP_MINIT_FUNCTION(snmp)
                    381: {
                    382:        init_snmp("snmpapp");
                    383: 
                    384: #ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
                    385:        /* Prevent update of the snmpapp.conf file */
                    386:        netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
                    387: #endif
                    388: 
                    389: #ifdef HAVE_NET_SNMP
                    390:        REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_FULL", NETSNMP_OID_OUTPUT_FULL, CONST_CS | CONST_PERSISTENT);
                    391:        REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NUMERIC", NETSNMP_OID_OUTPUT_NUMERIC, CONST_CS | CONST_PERSISTENT);
                    392: #endif
                    393: 
                    394:        REGISTER_LONG_CONSTANT("SNMP_VALUE_LIBRARY", SNMP_VALUE_LIBRARY, CONST_CS | CONST_PERSISTENT);
                    395:        REGISTER_LONG_CONSTANT("SNMP_VALUE_PLAIN", SNMP_VALUE_PLAIN, CONST_CS | CONST_PERSISTENT);
                    396:        REGISTER_LONG_CONSTANT("SNMP_VALUE_OBJECT", SNMP_VALUE_OBJECT, CONST_CS | CONST_PERSISTENT);
                    397: 
                    398:        REGISTER_LONG_CONSTANT("SNMP_BIT_STR", ASN_BIT_STR, CONST_CS | CONST_PERSISTENT);
                    399:        REGISTER_LONG_CONSTANT("SNMP_OCTET_STR", ASN_OCTET_STR, CONST_CS | CONST_PERSISTENT);
                    400:        REGISTER_LONG_CONSTANT("SNMP_OPAQUE", ASN_OPAQUE, CONST_CS | CONST_PERSISTENT);
                    401:        REGISTER_LONG_CONSTANT("SNMP_NULL", ASN_NULL, CONST_CS | CONST_PERSISTENT);
                    402:        REGISTER_LONG_CONSTANT("SNMP_OBJECT_ID", ASN_OBJECT_ID, CONST_CS | CONST_PERSISTENT);
                    403:        REGISTER_LONG_CONSTANT("SNMP_IPADDRESS", ASN_IPADDRESS, CONST_CS | CONST_PERSISTENT);
                    404:        REGISTER_LONG_CONSTANT("SNMP_COUNTER", ASN_GAUGE, CONST_CS | CONST_PERSISTENT);
                    405:        REGISTER_LONG_CONSTANT("SNMP_UNSIGNED", ASN_UNSIGNED, CONST_CS | CONST_PERSISTENT);
                    406:        REGISTER_LONG_CONSTANT("SNMP_TIMETICKS", ASN_TIMETICKS, CONST_CS | CONST_PERSISTENT);
                    407:        REGISTER_LONG_CONSTANT("SNMP_UINTEGER", ASN_UINTEGER, CONST_CS | CONST_PERSISTENT);
                    408:        REGISTER_LONG_CONSTANT("SNMP_INTEGER", ASN_INTEGER, CONST_CS | CONST_PERSISTENT);
                    409:        REGISTER_LONG_CONSTANT("SNMP_COUNTER64", ASN_COUNTER64, CONST_CS | CONST_PERSISTENT);
                    410: 
                    411:        return SUCCESS;
                    412: }
                    413: /* }}} */
                    414: 
                    415: /* {{{ PHP_MSHUTDOWN_FUNCTION
                    416:  */
                    417: PHP_MSHUTDOWN_FUNCTION(snmp)
                    418: {
                    419:        snmp_shutdown("snmpapp");
                    420: 
                    421:        return SUCCESS;
                    422: }
                    423: /* }}} */
                    424: 
                    425: /* {{{ PHP_MINFO_FUNCTION
                    426:  */
                    427: PHP_MINFO_FUNCTION(snmp)
                    428: {
                    429:        php_info_print_table_start();
                    430: #ifdef HAVE_NET_SNMP
                    431:        php_info_print_table_row(2, "NET-SNMP Support", "enabled");
                    432:        php_info_print_table_row(2, "NET-SNMP Version", netsnmp_get_version());
                    433: #else
                    434:        php_info_print_table_row(2, "UCD-SNMP Support", "enabled");
                    435:        php_info_print_table_row(2, "UCD-SNMP Version", VersionInfo);
                    436: #endif
                    437:        php_info_print_table_end();
                    438: }
                    439: /* }}} */
                    440: 
                    441: static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_DC)
                    442: {
                    443:        zval *val;
                    444: #if I64CHARSZ > 2047
                    445:        char buf[I64CHARSZ + 1];
                    446: #else
                    447:        char buf[2048];
                    448: #endif
                    449: 
                    450:        buf[0] = 0;
                    451: 
                    452:        if (SNMP_G(valueretrieval) == SNMP_VALUE_LIBRARY) {
                    453: #ifdef HAVE_NET_SNMP
                    454:                snprint_value(buf, sizeof(buf), vars->name, vars->name_length, vars);
                    455: #else
                    456:                sprint_value(buf,vars->name, vars->name_length, vars);
                    457: #endif
                    458:                ZVAL_STRING(snmpval, buf, 1);
                    459:                return;
                    460:        }
                    461: 
                    462:        MAKE_STD_ZVAL(val);
                    463: 
                    464:        switch (vars->type) {
                    465:        case ASN_BIT_STR:               /* 0x03, asn1.h */
                    466:                ZVAL_STRINGL(val, vars->val.bitstring, vars->val_len, 1);
                    467:                break;
                    468: 
                    469:        case ASN_OCTET_STR:             /* 0x04, asn1.h */
                    470:        case ASN_OPAQUE:                /* 0x44, snmp_impl.h */
                    471:                ZVAL_STRINGL(val, vars->val.string, vars->val_len, 1);
                    472:                break;
                    473: 
                    474:        case ASN_NULL:                  /* 0x05, asn1.h */
                    475:                ZVAL_NULL(val);
                    476:                break;
                    477: 
                    478:        case ASN_OBJECT_ID:             /* 0x06, asn1.h */
                    479: #ifdef HAVE_NET_SNMP
                    480:                snprint_objid(buf, sizeof(buf), vars->val.objid, vars->val_len / sizeof(oid));
                    481: #else
                    482:                sprint_objid(buf, vars->val.objid, vars->val_len / sizeof(oid));
                    483: #endif
                    484: 
                    485:                ZVAL_STRING(val, buf, 1);
                    486:                break;
                    487: 
                    488:        case ASN_IPADDRESS:             /* 0x40, snmp_impl.h */
                    489:                snprintf(buf, sizeof(buf)-1, "%d.%d.%d.%d",
                    490:                         (vars->val.string)[0], (vars->val.string)[1],
                    491:                         (vars->val.string)[2], (vars->val.string)[3]);
                    492:                buf[sizeof(buf)-1]=0;
                    493:                ZVAL_STRING(val, buf, 1);
                    494:                break;
                    495: 
                    496:        case ASN_COUNTER:               /* 0x41, snmp_impl.h */
                    497:        case ASN_GAUGE:                 /* 0x42, snmp_impl.h */
                    498:        /* ASN_UNSIGNED is the same as ASN_GAUGE */
                    499:        case ASN_TIMETICKS:             /* 0x43, snmp_impl.h */
                    500:        case ASN_UINTEGER:              /* 0x47, snmp_impl.h */
                    501:                snprintf(buf, sizeof(buf)-1, "%lu", *vars->val.integer);
                    502:                buf[sizeof(buf)-1]=0;
                    503:                ZVAL_STRING(val, buf, 1);
                    504:                break;
                    505: 
                    506:        case ASN_INTEGER:               /* 0x02, asn1.h */
                    507:                snprintf(buf, sizeof(buf)-1, "%ld", *vars->val.integer);
                    508:                buf[sizeof(buf)-1]=0;
                    509:                ZVAL_STRING(val, buf, 1);
                    510:                break;
                    511: 
                    512:        case ASN_COUNTER64:             /* 0x46, snmp_impl.h */
                    513:                printU64(buf, vars->val.counter64);
                    514:                ZVAL_STRING(val, buf, 1);
                    515:                break;
                    516: 
                    517:        default:
                    518:                ZVAL_STRING(val, "Unknown value type", 1);
                    519:                break;
                    520:        }
                    521: 
                    522:        if (SNMP_G(valueretrieval) == SNMP_VALUE_PLAIN) {
                    523:                *snmpval = *val;
                    524:                zval_copy_ctor(snmpval);
                    525:        } else {
                    526:                object_init(snmpval);
                    527:                add_property_long(snmpval, "type", vars->type);
                    528:                add_property_zval(snmpval, "value", val);
                    529:        }
                    530: }
                    531: 
                    532: /* {{{ php_snmp_internal
                    533: *
                    534: * Generic SNMP object fetcher (for all SNMP versions)
                    535: *
                    536: * st=SNMP_CMD_GET   get - query an agent with SNMP-GET.
                    537: * st=SNMP_CMD_GETNEXT   getnext - query an agent with SNMP-GETNEXT.
                    538: * st=SNMP_CMD_WALK   walk - walk the mib and return a single dimensional array 
                    539: *          containing the values.
                    540: * st=SNMP_CMD_REALWALK   realwalk() and walkoid() - walk the mib and return an 
                    541: *          array of oid,value pairs.
                    542: * st=SNMP_CMD_SET  set() - query an agent and set a single value
                    543: *
                    544: */
                    545: static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, 
                    546:                                                        struct snmp_session *session,
                    547:                                                        char *objid,
                    548:                                                        char type,
                    549:                                                        char* value) 
                    550: {
                    551:        struct snmp_session *ss;
                    552:        struct snmp_pdu *pdu=NULL, *response;
                    553:        struct variable_list *vars;
                    554:        oid name[MAX_NAME_LEN];
                    555:        size_t name_length;
                    556:        oid root[MAX_NAME_LEN];
                    557:        size_t rootlen = 0;
                    558:        int gotroot = 0;
                    559:        int status, count;
                    560:        char buf[2048];
                    561:        char buf2[2048];
                    562:        int keepwalking=1;
                    563:        char *err;
                    564:        zval *snmpval = NULL;
                    565: 
                    566:        if (st >= SNMP_CMD_WALK) { /* walk */
                    567:                rootlen = MAX_NAME_LEN;
                    568:                if (strlen(objid)) { /* on a walk, an empty string means top of tree - no error */
                    569:                        if (snmp_parse_oid(objid, root, &rootlen)) {
                    570:                                gotroot = 1;
                    571:                        } else {
                    572:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid);
                    573:                        }
                    574:                }
                    575: 
                    576:                if (!gotroot) {
                    577:                        memmove((char *) root, (char *) objid_mib, sizeof(objid_mib));
                    578:                        rootlen = sizeof(objid_mib) / sizeof(oid);
                    579:                        gotroot = 1;
                    580:                }
                    581:        }
                    582: 
                    583:        if ((ss = snmp_open(session)) == NULL) {
                    584:                snmp_error(session, NULL, NULL, &err);
                    585:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open snmp connection: %s", err);
                    586:                free(err);
                    587:                RETURN_FALSE;
                    588:        }
                    589: 
                    590:        if (st >= SNMP_CMD_WALK) {
                    591:                memmove((char *)name, (char *)root, rootlen * sizeof(oid));
                    592:                name_length = rootlen;
                    593:                switch(st) {
                    594:                        case SNMP_CMD_WALK:
                    595:                        case SNMP_CMD_REALWALK:
                    596:                                array_init(return_value);
                    597:                                break;
                    598:                        default:
                    599:                                RETVAL_TRUE;
                    600:                                break;
                    601:                }
                    602:        }
                    603: 
                    604:        while (keepwalking) {
                    605:                keepwalking = 0;
                    606:                if ((st == SNMP_CMD_GET) || (st == SNMP_CMD_GETNEXT)) {
                    607:                        name_length = MAX_OID_LEN;
                    608:                        if (!snmp_parse_oid(objid, name, &name_length)) {
                    609:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid);
                    610:                                snmp_close(ss);
                    611:                                RETURN_FALSE;
                    612:                        }
                    613:                        pdu = snmp_pdu_create((st == SNMP_CMD_GET) ? SNMP_MSG_GET : SNMP_MSG_GETNEXT);
                    614:                        snmp_add_null_var(pdu, name, name_length);
                    615:                } else if (st == SNMP_CMD_SET) {
                    616:                        pdu = snmp_pdu_create(SNMP_MSG_SET);
                    617:                        if (snmp_add_var(pdu, name, name_length, type, value)) {
                    618: #ifdef HAVE_NET_SNMP
                    619:                                snprint_objid(buf, sizeof(buf), name, name_length);
                    620: #else
                    621:                                sprint_objid(buf, name, name_length);
                    622: #endif
                    623:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not add variable: %s %c %s", buf, type, value);
                    624:                                snmp_free_pdu(pdu);
                    625:                                snmp_close(ss);
                    626:                                RETURN_FALSE;
                    627:                        }
                    628:                } else if (st >= SNMP_CMD_WALK) {
                    629:                        if (session->version == SNMP_VERSION_1) {
                    630:                                pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
                    631:                        } else {
                    632:                                pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
                    633:                                pdu->non_repeaters = 0;
                    634:                                pdu->max_repetitions = 20;
                    635:                        }
                    636:                        snmp_add_null_var(pdu, name, name_length);
                    637:                }
                    638: 
                    639: retry:
                    640:                status = snmp_synch_response(ss, pdu, &response);
                    641:                if (status == STAT_SUCCESS) {
                    642:                        if (response->errstat == SNMP_ERR_NOERROR) {
                    643:                                for (vars = response->variables; vars; vars = vars->next_variable) {
                    644:                                        if (st >= SNMP_CMD_WALK && st != SNMP_CMD_SET && 
                    645:                                                (vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid)))) {
                    646:                                                continue;       /* not part of this subtree */
                    647:                                        }
                    648: 
                    649:                                        if (st != SNMP_CMD_SET) {
                    650:                                                MAKE_STD_ZVAL(snmpval);
                    651:                                                php_snmp_getvalue(vars, snmpval TSRMLS_CC);
                    652:                                        }
                    653: 
                    654:                                        if (st == SNMP_CMD_GET) {
                    655:                                                *return_value = *snmpval;
                    656:                                                zval_copy_ctor(return_value);
                    657:                                                zval_ptr_dtor(&snmpval);
                    658:                                                snmp_free_pdu(response);
                    659:                                                snmp_close(ss);
                    660:                                                return;
                    661:                                        } else if (st == SNMP_CMD_GETNEXT) {
                    662:                                                *return_value = *snmpval;
                    663:                                                zval_copy_ctor(return_value);
                    664:                                                snmp_free_pdu(response);
                    665:                                                snmp_close(ss);
                    666:                                                return;
                    667:                                        } else if (st == SNMP_CMD_WALK) {
                    668:                                                add_next_index_zval(return_value,snmpval); /* Add to returned array */
                    669:                                        } else if (st == SNMP_CMD_REALWALK && vars->type != SNMP_ENDOFMIBVIEW && vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) {
                    670: #ifdef HAVE_NET_SNMP
                    671:                                                snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
                    672: #else
                    673:                                                sprint_objid(buf2, vars->name, vars->name_length);
                    674: #endif
                    675:                                                add_assoc_zval(return_value,buf2,snmpval);
                    676:                                        }
                    677:                                        if (st >= SNMP_CMD_WALK && st != SNMP_CMD_SET) {
                    678:                                                if (vars->type != SNMP_ENDOFMIBVIEW && 
                    679:                                                        vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) {
                    680:                                                        if (snmp_oid_compare(name, name_length, vars->name, vars->name_length) >= 0) {
                    681:                                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error: OID not increasing: %s",name);
                    682:                                                                keepwalking = 0;
                    683:                                                        } else {
                    684:                                                                memmove((char *)name, (char *)vars->name,vars->name_length * sizeof(oid));
                    685:                                                                name_length = vars->name_length;
                    686:                                                                keepwalking = 1;
                    687:                                                        }
                    688:                                                }
                    689:                                        }
                    690:                                }       
                    691:                        } else {
                    692:                                if ((st != SNMP_CMD_WALK && st != SNMP_CMD_REALWALK) || response->errstat != SNMP_ERR_NOSUCHNAME) {
                    693:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error in packet: %s", snmp_errstring(response->errstat));
                    694:                                        if (response->errstat == SNMP_ERR_NOSUCHNAME) {
                    695:                                                for (count=1, vars = response->variables; vars && count != response->errindex;
                    696:                                                vars = vars->next_variable, count++);
                    697:                                                if (vars) {
                    698: #ifdef HAVE_NET_SNMP
                    699:                                                        snprint_objid(buf, sizeof(buf), vars->name, vars->name_length);
                    700: #else
                    701:                                                        sprint_objid(buf,vars->name, vars->name_length);
                    702: #endif
                    703:                                                }
                    704:                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "This name does not exist: %s",buf);
                    705:                                        }
                    706:                                        if (st == SNMP_CMD_GET) {
                    707:                                                if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GET)) != NULL) {
                    708:                                                        snmp_free_pdu(response);
                    709:                                                        goto retry;
                    710:                                                }
                    711:                                        } else if (st == SNMP_CMD_SET) {
                    712:                                                if ((pdu = snmp_fix_pdu(response, SNMP_MSG_SET)) != NULL) {
                    713:                                                        snmp_free_pdu(response);
                    714:                                                        goto retry;
                    715:                                                }
                    716:                                        } else if (st == SNMP_CMD_GETNEXT) {
                    717:                                                if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) != NULL) {
                    718:                                                        snmp_free_pdu(response);
                    719:                                                        goto retry;
                    720:                                                }
                    721:                                        } else if (st >= SNMP_CMD_WALK) { /* Here we do walks. */
                    722:                                                if ((pdu = snmp_fix_pdu(response, ((session->version == SNMP_VERSION_1)
                    723:                                                                                ? SNMP_MSG_GETNEXT
                    724:                                                                                : SNMP_MSG_GETBULK))) != NULL) {
                    725:                                                        snmp_free_pdu(response);
                    726:                                                        goto retry;
                    727:                                                }
                    728:                                        }
                    729:                                        snmp_free_pdu(response);
                    730:                                        snmp_close(ss);
                    731:                                        if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
                    732:                                                zval_dtor(return_value);
                    733:                                        }
                    734:                                        RETURN_FALSE;
                    735:                                }
                    736:                        }
                    737:                } else if (status == STAT_TIMEOUT) {
                    738:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No response from %s", session->peername);
                    739:                        if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
                    740:                                zval_dtor(return_value);
                    741:                        }
                    742:                        snmp_close(ss);
                    743:                        RETURN_FALSE;
                    744:                } else {    /* status == STAT_ERROR */
                    745:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred, quitting");
                    746:                        if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
                    747:                                zval_dtor(return_value);
                    748:                        }
                    749:                        snmp_close(ss);
                    750:                        RETURN_FALSE;
                    751:                }
                    752:                if (response) {
                    753:                        snmp_free_pdu(response);
                    754:                }
                    755:        } /* keepwalking */
                    756:        snmp_close(ss);
                    757: }
                    758: /* }}} */
                    759: 
                    760: /* {{{ php_snmp
                    761: *
                    762: * Generic community based SNMP handler for version 1 and 2.
                    763: * This function makes use of the internal SNMP object fetcher.
                    764: * The object fetcher is shared with SNMPv3.
                    765: *
                    766: * st=SNMP_CMD_GET   get - query an agent with SNMP-GET.
                    767: * st=SNMP_CMD_GETNEXT   getnext - query an agent with SNMP-GETNEXT.
                    768: * st=SNMP_CMD_WALK   walk - walk the mib and return a single dimensional array 
                    769: *          containing the values.
                    770: * st=SNMP_CMD_REALWALK   realwalk() and walkoid() - walk the mib and return an 
                    771: *          array of oid,value pairs.
                    772: * st=5-8 ** Reserved **
                    773: * st=SNMP_CMD_SET  set() - query an agent and set a single value
                    774: *
                    775: */
                    776: static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) 
                    777: {
                    778:        char *a1, *a2, *a3;
                    779:        int a1_len, a2_len, a3_len;
                    780:        struct snmp_session session;
                    781:        long timeout = SNMP_DEFAULT_TIMEOUT;
                    782:        long retries = SNMP_DEFAULT_RETRIES;
                    783:        char type = (char) 0;
                    784:        char *value = (char *) 0, *stype = "";
                    785:        int value_len, stype_len;
                    786:        char hostname[MAX_NAME_LEN];
                    787:        int remote_port = 161;
                    788:        char *pptr;
                    789:        int argc = ZEND_NUM_ARGS();
                    790: 
                    791:        if (st == SNMP_CMD_SET) {
                    792:                if (zend_parse_parameters(argc TSRMLS_CC, "sssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len, &stype, &stype_len, &value, &value_len, &timeout, &retries) == FAILURE) {
                    793:                        return;
                    794:                }
                    795:        } else {
                    796:                /* SNMP_CMD_GET
                    797:                 * SNMP_CMD_GETNEXT
                    798:                 * SNMP_CMD_WALK
                    799:                 * SNMP_CMD_REALWALK
                    800:                 */
                    801:                if (zend_parse_parameters(argc TSRMLS_CC, "sss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len, &timeout, &retries) == FAILURE) {
                    802:                        return;
                    803:                }
                    804:        }
                    805:        
                    806:        if (st == SNMP_CMD_SET) {
                    807:                type = stype[0];
                    808:        } 
                    809: 
                    810:        snmp_sess_init(&session);
                    811:        strlcpy(hostname, a1, sizeof(hostname));
                    812:        if ((pptr = strchr (hostname, ':'))) {
                    813:                remote_port = strtol (pptr + 1, NULL, 0);
                    814:        }
                    815: 
                    816:        session.peername = hostname;
                    817:        session.remote_port = remote_port;
                    818:        session.version = version;
                    819:        /*
                    820:        * FIXME: potential memory leak
                    821:        * This is a workaround for an "artifact" (Mike Slifcak)
                    822:        * in (at least) ucd-snmp 3.6.1 which frees
                    823:        * memory it did not allocate
                    824:        */
                    825: #ifdef UCD_SNMP_HACK
                    826:        session.community = (u_char *)strdup(a2); /* memory freed by SNMP library, strdup NOT estrdup */
                    827: #else
                    828:        session.community = (u_char *)a2;
                    829: #endif
                    830:        session.community_len = a2_len;
                    831:        session.retries = retries;
                    832:        session.timeout = timeout;
                    833:        
                    834:        session.authenticator = NULL;
                    835: 
                    836:        php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session, a3, type, value);
                    837: }
                    838: /* }}} */
                    839: 
                    840: /* {{{ proto string snmpget(string host, string community, string object_id [, int timeout [, int retries]]) 
                    841:    Fetch a SNMP object */
                    842: PHP_FUNCTION(snmpget)
                    843: {
                    844:        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_1);
                    845: }
                    846: /* }}} */
                    847: 
                    848: /* {{{ proto string snmpgetnext(string host, string community, string object_id [, int timeout [, int retries]]) 
                    849:    Fetch a SNMP object */
                    850: PHP_FUNCTION(snmpgetnext)
                    851: {
                    852:        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_1);
                    853: }
                    854: /* }}} */
                    855: 
                    856: /* {{{ proto array snmpwalk(string host, string community, string object_id [, int timeout [, int retries]]) 
                    857:    Return all objects under the specified object id */
                    858: PHP_FUNCTION(snmpwalk)
                    859: {
                    860:        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_1);
                    861: }
                    862: /* }}} */
                    863: 
                    864: /* {{{ proto array snmprealwalk(string host, string community, string object_id [, int timeout [, int retries]])
                    865:    Return all objects including their respective object id withing the specified one */
                    866: PHP_FUNCTION(snmprealwalk)
                    867: {
                    868:        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_1);
                    869: }
                    870: /* }}} */
                    871: 
                    872: /* {{{ proto bool snmp_get_quick_print(void)
                    873:    Return the current status of quick_print */
                    874: PHP_FUNCTION(snmp_get_quick_print)
                    875: {
                    876:        if (zend_parse_parameters_none() == FAILURE) {
                    877:                return;
                    878:        }
                    879: 
                    880: #ifdef HAVE_NET_SNMP
                    881:        RETURN_BOOL(netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT));
                    882: #else
                    883:        RETURN_BOOL(snmp_get_quick_print());
                    884: #endif
                    885: }
                    886: /* }}} */
                    887: 
                    888: /* {{{ proto void snmp_set_quick_print(int quick_print)
                    889:    Return all objects including their respective object id withing the specified one */
                    890: PHP_FUNCTION(snmp_set_quick_print)
                    891: {
                    892:        long a1;
                    893: 
                    894:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
                    895:                return;
                    896:        }
                    897: 
                    898: #ifdef HAVE_NET_SNMP
                    899:        netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, (int) a1);
                    900: #else
                    901:        snmp_set_quick_print((int)a1);
                    902: #endif
                    903: }
                    904: /* }}} */
                    905: 
                    906: #ifdef HAVE_NET_SNMP
                    907: /* {{{ proto void snmp_set_enum_print(int enum_print)
                    908:    Return all values that are enums with their enum value instead of the raw integer */
                    909: PHP_FUNCTION(snmp_set_enum_print)
                    910: {
                    911:        long a1;
                    912: 
                    913:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
                    914:                return;
                    915:        }
                    916: 
                    917:        netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, (int) a1);
                    918: } 
                    919: /* }}} */
                    920: 
                    921: /* {{{ proto void snmp_set_oid_output_format(int oid_format)
                    922:    Set the OID output format. */
                    923: PHP_FUNCTION(snmp_set_oid_output_format)
                    924: {
                    925:        long a1;
                    926: 
                    927:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
                    928:                return;
                    929:        }
                    930: 
                    931:        switch ((int) a1) {
                    932:                case 0:
                    933:                case NETSNMP_OID_OUTPUT_FULL:
                    934:                        a1 = NETSNMP_OID_OUTPUT_FULL;
                    935:                        break;
                    936: 
                    937:                default:
                    938:                case NETSNMP_OID_OUTPUT_NUMERIC:
                    939:                        a1 = NETSNMP_OID_OUTPUT_NUMERIC;
                    940:                        break;
                    941:        }
                    942: 
                    943:        netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, a1);
                    944: } 
                    945: /* }}} */
                    946: #endif
                    947: 
                    948: /* {{{ proto int snmpset(string host, string community, string object_id, string type, mixed value [, int timeout [, int retries]]) 
                    949:    Set the value of a SNMP object */
                    950: PHP_FUNCTION(snmpset)
                    951: {
                    952:        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_SET, SNMP_VERSION_1);
                    953: }
                    954: /* }}} */
                    955: 
                    956: /* {{{ int netsnmp_session_set_sec_name(struct snmp_session *s, char *name)
                    957:    Set the security name in the snmpv3 session */
                    958: static int netsnmp_session_set_sec_name(struct snmp_session *s, char *name)
                    959: {
                    960:        if ((s) && (name)) {
                    961:                s->securityName = strdup(name);
                    962:                s->securityNameLen = strlen(s->securityName);
                    963:                return (0);
                    964:        }
                    965:        return (-1);
                    966: }
                    967: /* }}} */
                    968: 
                    969: /* {{{ int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
                    970:    Set the security level in the snmpv3 session */
                    971: static int netsnmp_session_set_sec_level(struct snmp_session *s, char *level TSRMLS_DC)
                    972: {
                    973:        if ((s) && (level)) {
                    974:                if (!strcasecmp(level, "noAuthNoPriv") || !strcasecmp(level, "nanp")) {
                    975:                        s->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
                    976:                        return (0);
                    977:                } else if (!strcasecmp(level, "authNoPriv") || !strcasecmp(level, "anp")) {
                    978:                        s->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
                    979:                        return (0);
                    980:                } else if (!strcasecmp(level, "authPriv") || !strcasecmp(level, "ap")) {
                    981:                        s->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
                    982:                        return (0);
                    983:                }
                    984:        }
                    985:        return (-1);
                    986: }
                    987: /* }}} */
                    988: 
                    989: /* {{{ int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot)
                    990:    Set the authentication protocol in the snmpv3 session */
                    991: static int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
                    992: {
                    993:        if ((s) && (prot)) {
                    994:                if (!strcasecmp(prot, "MD5")) {
                    995:                        s->securityAuthProto = usmHMACMD5AuthProtocol;
                    996:                        s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
                    997:                        return (0);
                    998:                } else if (!strcasecmp(prot, "SHA")) {
                    999:                        s->securityAuthProto = usmHMACSHA1AuthProtocol;
                   1000:                        s->securityAuthProtoLen = OIDSIZE(usmHMACSHA1AuthProtocol);
                   1001:                        return (0);
                   1002:                }
                   1003:        }
                   1004:        return (-1);
                   1005: }
                   1006: /* }}} */
                   1007: 
                   1008: /* {{{ int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot)
                   1009:    Set the security protocol in the snmpv3 session */
                   1010: static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
                   1011: {
                   1012:        if ((s) && (prot)) {
                   1013:                if (!strcasecmp(prot, "DES")) {
                   1014:                        s->securityPrivProto = usmDESPrivProtocol;
                   1015:                        s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
                   1016:                        return (0);
                   1017: #ifdef HAVE_AES
                   1018:                } else if (!strcasecmp(prot, "AES128")
                   1019: #ifdef SNMP_VALIDATE_ERR
                   1020: /* 
                   1021: * In Net-SNMP before 5.2, the following symbols exist:
                   1022: * usmAES128PrivProtocol, usmAES192PrivProtocol, usmAES256PrivProtocol
                   1023: * In an effort to be more standards-compliant, 5.2 removed the last two.
                   1024: * As of 5.2, the symbols are:
                   1025: * usmAESPrivProtocol, usmAES128PrivProtocol
                   1026: * 
                   1027: * As we want this extension to compile on both versions, we use the latter
                   1028: * symbol on purpose, as it's defined to be the same as the former.
                   1029: *
                   1030: * However, in 5.2 the type of usmAES128PrivProtocol is a pointer, not an
                   1031: * array, so we cannot use the OIDSIZE macro because it uses sizeof().
                   1032: *
                   1033: */
                   1034:                        || !strcasecmp(prot, "AES")) {
                   1035:                        s->securityPrivProto = usmAES128PrivProtocol;
                   1036:                        s->securityPrivProtoLen = USM_PRIV_PROTO_AES128_LEN;
                   1037:                        return (0);
                   1038: #else                  
                   1039:                ) {
                   1040:                        s->securityPrivProto = usmAES128PrivProtocol;
                   1041:                        s->securityPrivProtoLen = OIDSIZE(usmAES128PrivProtocol);
                   1042:                        return (0);
                   1043:                } else if (!strcasecmp(prot, "AES192")) {
                   1044:                        s->securityPrivProto = usmAES192PrivProtocol;
                   1045:                        s->securityPrivProtoLen = OIDSIZE(usmAES192PrivProtocol);
                   1046:                        return (0);
                   1047:                } else if (!strcasecmp(prot, "AES256")) {
                   1048:                        s->securityPrivProto = usmAES256PrivProtocol;
                   1049:                        s->securityPrivProtoLen = OIDSIZE(usmAES256PrivProtocol);
                   1050:                        return (0);
                   1051: #endif
                   1052: #endif
                   1053:                }
                   1054:        }
                   1055:        return (-1);
                   1056: }
                   1057: /* }}} */
                   1058: 
                   1059: /* {{{ int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass)
                   1060:    Make key from pass phrase in the snmpv3 session */
                   1061: static int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass TSRMLS_DC)
                   1062: {
                   1063:        /*
                   1064:         * make master key from pass phrases 
                   1065:         */
                   1066:        if ((s) && (pass) && strlen(pass)) {
                   1067:                s->securityAuthKeyLen = USM_AUTH_KU_LEN;
                   1068:                if (s->securityAuthProto == NULL) {
                   1069:                        /* get .conf set default */
                   1070:                        const oid *def = get_default_authtype(&(s->securityAuthProtoLen));
                   1071:                        s->securityAuthProto = snmp_duplicate_objid(def, s->securityAuthProtoLen);
                   1072:                }
                   1073:                if (s->securityAuthProto == NULL) {
                   1074:                        /* assume MD5 */
                   1075:                        s->securityAuthProto =
                   1076:                                snmp_duplicate_objid(usmHMACMD5AuthProtocol, OIDSIZE(usmHMACMD5AuthProtocol));
                   1077:                        s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
                   1078:                }
                   1079:                if (generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
                   1080:                                (u_char *) pass, strlen(pass),
                   1081:                                s->securityAuthKey, &(s->securityAuthKeyLen)) != SNMPERR_SUCCESS) {
                   1082:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for authentication pass phrase");
                   1083:                        return (-2);
                   1084:                }
                   1085:                return (0);
                   1086:        }
                   1087:        return (-1);
                   1088: }
                   1089: /* }}} */
                   1090: 
                   1091: /* {{{ int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass)
                   1092:    Make key from pass phrase in the snmpv3 session */
                   1093: static int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass TSRMLS_DC)
                   1094: {
                   1095:        if ((s) && (pass) && strlen(pass)) {
                   1096:                s->securityPrivKeyLen = USM_PRIV_KU_LEN;
                   1097:                if (s->securityPrivProto == NULL) {
                   1098:                        /* get .conf set default */
                   1099:                        const oid *def = get_default_privtype(&(s->securityPrivProtoLen));
                   1100:                        s->securityPrivProto = snmp_duplicate_objid(def, s->securityPrivProtoLen);
                   1101:                }
                   1102:                if (s->securityPrivProto == NULL) {
                   1103:                        /* assume DES */
                   1104:                        s->securityPrivProto = snmp_duplicate_objid(usmDESPrivProtocol,
                   1105:                                OIDSIZE(usmDESPrivProtocol));
                   1106:                        s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
                   1107:                }
                   1108:                if (generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
                   1109:                                pass, strlen(pass),
                   1110:                                s->securityPrivKey, &(s->securityPrivKeyLen)) != SNMPERR_SUCCESS) {
                   1111:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for privacy pass phrase");
                   1112:                        return (-2);
                   1113:                }
                   1114:                return (0);
                   1115:        }
                   1116:        return (-1);
                   1117: }
                   1118: /* }}} */
                   1119: 
                   1120: /* {{{ proto string snmp2_get(string host, string community, string object_id [, int timeout [, int retries]]) 
                   1121:    Fetch a SNMP object */
                   1122: PHP_FUNCTION(snmp2_get)
                   1123: {
                   1124:        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_2c);
                   1125: }
                   1126: /* }}} */
                   1127: 
                   1128: /* {{{ proto string snmp2_getnext(string host, string community, string object_id [, int timeout [, int retries]]) 
                   1129:    Fetch a SNMP object */
                   1130: PHP_FUNCTION(snmp2_getnext)
                   1131: {
                   1132:        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_2c);
                   1133: }
                   1134: /* }}} */
                   1135: 
                   1136: /* {{{ proto array snmp2_walk(string host, string community, string object_id [, int timeout [, int retries]]) 
                   1137:    Return all objects under the specified object id */
                   1138: PHP_FUNCTION(snmp2_walk)
                   1139: {
                   1140:        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_2c);
                   1141: }
                   1142: /* }}} */
                   1143: 
                   1144: /* {{{ proto array snmp2_real_walk(string host, string community, string object_id [, int timeout [, int retries]])
                   1145:    Return all objects including their respective object id withing the specified one */
                   1146: PHP_FUNCTION(snmp2_real_walk)
                   1147: {
                   1148:        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_2c);
                   1149: }
                   1150: /* }}} */
                   1151: 
                   1152: /* {{{ proto int snmp2_set(string host, string community, string object_id, string type, mixed value [, int timeout [, int retries]]) 
                   1153:    Set the value of a SNMP object */
                   1154: PHP_FUNCTION(snmp2_set)
                   1155: {
                   1156:        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_SET, SNMP_VERSION_2c);
                   1157: }
                   1158: /* }}} */
                   1159: 
                   1160: /* {{{ proto void php_snmpv3(INTERNAL_FUNCTION_PARAMETERS, int st)
                   1161: *
                   1162: * Generic SNMPv3 object fetcher
                   1163: * From here is passed on the common internal object fetcher.
                   1164: *
                   1165: * st=SNMP_CMD_GET   snmp3_get() - query an agent and return a single value.
                   1166: * st=SNMP_CMD_GETNEXT   snmp3_getnext() - query an agent and return the next single value.
                   1167: * st=SNMP_CMD_WALK   snmp3_walk() - walk the mib and return a single dimensional array 
                   1168: *                       containing the values.
                   1169: * st=SNMP_CMD_REALWALK   snmp3_real_walk() - walk the mib and return an 
                   1170: *                            array of oid,value pairs.
                   1171: * st=SNMP_CMD_SET  snmp3_set() - query an agent and set a single value
                   1172: *
                   1173: */
                   1174: static void php_snmpv3(INTERNAL_FUNCTION_PARAMETERS, int st)
                   1175: {
                   1176:        char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
                   1177:        int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len, a8_len;
                   1178:        struct snmp_session session;
                   1179:        long timeout = SNMP_DEFAULT_TIMEOUT;
                   1180:        long retries = SNMP_DEFAULT_RETRIES;
                   1181:        char type = (char) 0;
                   1182:        char *value = (char *) 0, *stype = "";
                   1183:        int stype_len, value_len;       
                   1184:        char hostname[MAX_NAME_LEN];
                   1185:        int remote_port = 161;
                   1186:        char *pptr;
                   1187:        int argc = ZEND_NUM_ARGS();
                   1188:        
                   1189:        if (st == SNMP_CMD_SET) {       
                   1190:                if (zend_parse_parameters(argc TSRMLS_CC, "ssssssssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
                   1191:                        &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &a8, &a8_len, &stype, &stype_len, &value, &value_len, &timeout, &retries) == FAILURE) {
                   1192:                        return;
                   1193:                }
                   1194:        } else {
                   1195:                /* SNMP_CMD_GET
                   1196:                 * SNMP_CMD_GETNEXT
                   1197:                 * SNMP_CMD_WALK
                   1198:                 * SNMP_CMD_REALWALK
                   1199:                 */
                   1200:                if (zend_parse_parameters(argc TSRMLS_CC, "ssssssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
                   1201:                        &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &a8, &a8_len, &timeout, &retries) == FAILURE) {
                   1202:                        return;
                   1203:                }
                   1204:        }
                   1205: 
                   1206:        snmp_sess_init(&session);
                   1207:        /* This is all SNMPv3 */
                   1208:        session.version = SNMP_VERSION_3;
                   1209: 
                   1210:        /* Reading the hostname and its optional non-default port number */
                   1211:        strlcpy(hostname, a1, sizeof(hostname));
                   1212:        if ((pptr = strchr(hostname, ':'))) {
                   1213:                remote_port = strtol(pptr + 1, NULL, 0);
                   1214:        }
                   1215:        session.peername = hostname;
                   1216:        session.remote_port = remote_port;
                   1217: 
                   1218:        /* Setting the security name. */
                   1219:        if (netsnmp_session_set_sec_name(&session, a2)) {
                   1220:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could net set security name: %s", a2);
                   1221:                RETURN_FALSE;
                   1222:        }
                   1223: 
                   1224:        /* Setting the security level. */
                   1225:        if (netsnmp_session_set_sec_level(&session, a3 TSRMLS_CC)) {
                   1226:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security level: %s", a3);
                   1227:                RETURN_FALSE;
                   1228:        }
                   1229: 
                   1230:        /* Setting the authentication protocol. */
                   1231:        if (netsnmp_session_set_auth_protocol(&session, a4 TSRMLS_CC)) {
                   1232:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid authentication protocol: %s", a4);
                   1233:                RETURN_FALSE;
                   1234:        }
                   1235: 
                   1236:        /* Setting the authentication passphrase. */
                   1237:        if (netsnmp_session_gen_auth_key(&session, a5 TSRMLS_CC)) {
                   1238:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not generate key for authentication pass phrase: %s", a5);
                   1239:                RETURN_FALSE;
                   1240:        }
                   1241: 
                   1242:        /* Setting the security protocol. */
                   1243:        if (netsnmp_session_set_sec_protocol(&session, a6 TSRMLS_CC) && a6_len) {
                   1244:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security protocol: %s", a6);
                   1245:                RETURN_FALSE;
                   1246:        }
                   1247: 
                   1248:        /* Setting the security protocol passphrase. */
                   1249:        if (netsnmp_session_gen_sec_key(&session, a7 TSRMLS_CC) && a7_len) {
                   1250:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not generate key for security pass phrase: %s", a7);
                   1251:                RETURN_FALSE;
                   1252:        }
                   1253: 
                   1254:        if (st == SNMP_CMD_SET) {
                   1255:                type = stype[0];
                   1256:        }
                   1257: 
                   1258:        session.retries = retries;
                   1259:        session.timeout = timeout;
                   1260: 
                   1261:        php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session, a8, type, value);
                   1262: }
                   1263: /* }}} */
                   1264: 
                   1265: /* {{{ proto int snmp3_get(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
                   1266:    Fetch the value of a SNMP object */
                   1267: PHP_FUNCTION(snmp3_get)
                   1268: {
                   1269:        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET);
                   1270: }
                   1271: /* }}} */
                   1272: 
                   1273: /* {{{ proto int snmp3_getnext(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
                   1274:    Fetch the value of a SNMP object */
                   1275: PHP_FUNCTION(snmp3_getnext)
                   1276: {
                   1277:        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT);
                   1278: }
                   1279: /* }}} */
                   1280: 
                   1281: /* {{{ proto int snmp3_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
                   1282:    Fetch the value of a SNMP object */
                   1283: PHP_FUNCTION(snmp3_walk)
                   1284: {
                   1285:        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK);
                   1286: }
                   1287: /* }}} */
                   1288: 
                   1289: /* {{{ proto int snmp3_real_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
                   1290:    Fetch the value of a SNMP object */
                   1291: PHP_FUNCTION(snmp3_real_walk)
                   1292: {
                   1293:        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_REALWALK);
                   1294: }
                   1295: /* }}} */
                   1296: 
                   1297: /* {{{ proto int snmp3_set(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id, string type, mixed value [, int timeout [, int retries]])
                   1298:    Fetch the value of a SNMP object */
                   1299: PHP_FUNCTION(snmp3_set)
                   1300: {
                   1301:        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET);
                   1302: }
                   1303: /* }}} */
                   1304: 
                   1305: /* {{{ proto void snmp_set_valueretrieval(int method)
                   1306:    Specify the method how the SNMP values will be returned */
                   1307: PHP_FUNCTION(snmp_set_valueretrieval)
                   1308: {
                   1309:        long method;
                   1310: 
                   1311:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
                   1312:                return;
                   1313:        }
                   1314: 
                   1315:        if ((method == SNMP_VALUE_LIBRARY) || (method == SNMP_VALUE_PLAIN) || (method == SNMP_VALUE_OBJECT)) {
                   1316:                SNMP_G(valueretrieval) = method;
                   1317:        }
                   1318: }
                   1319: /* }}} */
                   1320: 
                   1321: /* {{{ proto int snmp_get_valueretrieval()
                   1322:    Return the method how the SNMP values will be returned */
                   1323: PHP_FUNCTION(snmp_get_valueretrieval)
                   1324: {
                   1325:        RETURN_LONG(SNMP_G(valueretrieval));
                   1326: }
                   1327: /* }}} */
                   1328: 
                   1329: /* {{{ proto int snmp_read_mib(string filename)
                   1330:    Reads and parses a MIB file into the active MIB tree. */
                   1331: PHP_FUNCTION(snmp_read_mib)
                   1332: {
                   1333:        char *filename;
                   1334:        int filename_len;
                   1335: 
                   1336:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
                   1337:                return;
                   1338:        }
                   1339: 
                   1340:        /* Prevent read_mib() from printing any errors. */
                   1341:        snmp_disable_stderrlog();
                   1342:        
                   1343:        if (!read_mib(filename)) {
                   1344:                char *error = strerror(errno);
                   1345:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading MIB file '%s': %s", filename, error);
                   1346:                RETURN_FALSE;
                   1347:        }
                   1348:        RETURN_TRUE;
                   1349: }
                   1350: /* }}} */
                   1351: 
                   1352: #endif
                   1353: 
                   1354: /*
                   1355:  * Local variables:
                   1356:  * tab-width: 4
                   1357:  * c-basic-offset: 4
                   1358:  * End:
                   1359:  * vim600: sw=4 ts=4 fdm=marker
                   1360:  * vim<600: sw=4 ts=4
                   1361:  */

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