Back to index

php5  5.3.10
snmp.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
00016    |          Mike Jackson <mhjack@tscnet.com>                            |
00017    |          Steven Lawrance <slawrance@technologist.com>                |
00018    |          Harrie Hazewinkel <harrie@lisanza.net>                      |
00019    |          Johann Hanne <jonny@nurfuerspam.de>                         |
00020    +----------------------------------------------------------------------+
00021  */
00022 
00023 /* $Id: snmp.c 321634 2012-01-01 13:15:04Z felipe $ */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 
00029 #include "php.h"
00030 #include "ext/standard/info.h"
00031 #include "php_snmp.h"
00032 
00033 #if HAVE_SNMP
00034 
00035 #include <sys/types.h>
00036 #ifdef PHP_WIN32
00037 #include <winsock2.h>
00038 #include <errno.h>
00039 #include <process.h>
00040 #include "win32/time.h"
00041 #elif defined(NETWARE)
00042 #ifdef USE_WINSOCK
00043 #include <novsock2.h>
00044 #else
00045 #include <sys/socket.h>
00046 #endif
00047 #include <errno.h>
00048 #include <sys/timeval.h>
00049 #else
00050 #include <sys/socket.h>
00051 #include <netinet/in.h>
00052 #include <arpa/inet.h>
00053 #ifndef _OSD_POSIX
00054 #include <sys/errno.h>
00055 #else
00056 #include <errno.h>  /* BS2000/OSD uses <errno.h>, not <sys/errno.h> */
00057 #endif
00058 #include <netdb.h>
00059 #endif
00060 #ifdef HAVE_UNISTD_H
00061 #include <unistd.h>
00062 #endif
00063 
00064 #ifndef __P
00065 #ifdef __GNUC__
00066 #define __P(args) args
00067 #else
00068 #define __P(args) ()
00069 #endif
00070 #endif
00071 
00072 #ifdef HAVE_NET_SNMP
00073 #include <net-snmp/net-snmp-config.h>
00074 #include <net-snmp/net-snmp-includes.h>
00075 #else
00076 #ifdef HAVE_DEFAULT_STORE_H
00077 #include "default_store.h"
00078 #endif
00079 #include "asn1.h"
00080 #include "snmp_api.h"
00081 #include "snmp_client.h"
00082 #include "snmp_impl.h"
00083 #include "snmp.h"
00084 #include "snmpv3.h"
00085 #include "keytools.h"
00086 #include "parse.h"
00087 #include "mib.h"
00088 #ifndef PHP_WIN32
00089 /* this doesn't appear to be needed under win32 (perhaps at all)
00090  * and the header file is not present in my UCD-SNMP headers */
00091 # include "version.h"
00092 #endif
00093 #include "transform_oids.h"
00094 #endif
00095 /* Ugly macro, since the length of OIDs in UCD-SNMP and NET-SNMP
00096  * is different and this way the code is not full of 'ifdef's.
00097  */
00098 #define OIDSIZE(p) (sizeof(p)/sizeof(oid))
00099 
00100 /* For really old ucd-snmp versions.. */
00101 #ifndef HAVE_SNMP_PARSE_OID
00102 #define snmp_parse_oid read_objid
00103 #endif
00104 
00105 #define SNMP_VALUE_LIBRARY  0
00106 #define SNMP_VALUE_PLAIN    1
00107 #define SNMP_VALUE_OBJECT   2
00108 
00109 ZEND_DECLARE_MODULE_GLOBALS(snmp)
00110 static PHP_GINIT_FUNCTION(snmp);
00111 
00112 /* constant - can be shared among threads */
00113 static oid objid_mib[] = {1, 3, 6, 1, 2, 1};
00114 
00115 /* {{{ arginfo */
00116 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpget, 0, 0, 3)
00117        ZEND_ARG_INFO(0, host)
00118        ZEND_ARG_INFO(0, community)
00119        ZEND_ARG_INFO(0, object_id)
00120        ZEND_ARG_INFO(0, timeout)
00121        ZEND_ARG_INFO(0, retries)
00122 ZEND_END_ARG_INFO()
00123 
00124 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpgetnext, 0, 0, 3)
00125        ZEND_ARG_INFO(0, host)
00126        ZEND_ARG_INFO(0, community)
00127        ZEND_ARG_INFO(0, object_id)
00128        ZEND_ARG_INFO(0, timeout)
00129        ZEND_ARG_INFO(0, retries)
00130 ZEND_END_ARG_INFO()
00131 
00132 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpwalk, 0, 0, 3)
00133        ZEND_ARG_INFO(0, host)
00134        ZEND_ARG_INFO(0, community)
00135        ZEND_ARG_INFO(0, object_id)
00136        ZEND_ARG_INFO(0, timeout)
00137        ZEND_ARG_INFO(0, retries)
00138 ZEND_END_ARG_INFO()
00139 
00140 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmprealwalk, 0, 0, 3)
00141        ZEND_ARG_INFO(0, host)
00142        ZEND_ARG_INFO(0, community)
00143        ZEND_ARG_INFO(0, object_id)
00144        ZEND_ARG_INFO(0, timeout)
00145        ZEND_ARG_INFO(0, retries)
00146 ZEND_END_ARG_INFO()
00147 
00148 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_get_quick_print, 0, 0, 1)
00149        ZEND_ARG_INFO(0, d)
00150 ZEND_END_ARG_INFO()
00151 
00152 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_quick_print, 0, 0, 1)
00153        ZEND_ARG_INFO(0, quick_print)
00154 ZEND_END_ARG_INFO()
00155 
00156 #ifdef HAVE_NET_SNMP
00157 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_enum_print, 0, 0, 1)
00158        ZEND_ARG_INFO(0, enum_print)
00159 ZEND_END_ARG_INFO()
00160 
00161 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_oid_output_format, 0, 0, 1)
00162        ZEND_ARG_INFO(0, oid_format)
00163 ZEND_END_ARG_INFO()
00164 #endif
00165 
00166 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpset, 0, 0, 5)
00167        ZEND_ARG_INFO(0, host)
00168        ZEND_ARG_INFO(0, community)
00169        ZEND_ARG_INFO(0, object_id)
00170        ZEND_ARG_INFO(0, type)
00171        ZEND_ARG_INFO(0, value)
00172        ZEND_ARG_INFO(0, timeout)
00173        ZEND_ARG_INFO(0, retries)
00174 ZEND_END_ARG_INFO()
00175 
00176 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_get, 0, 0, 3)
00177        ZEND_ARG_INFO(0, host)
00178        ZEND_ARG_INFO(0, community)
00179        ZEND_ARG_INFO(0, object_id)
00180        ZEND_ARG_INFO(0, timeout)
00181        ZEND_ARG_INFO(0, retries)
00182 ZEND_END_ARG_INFO()
00183 
00184 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_getnext, 0, 0, 3)
00185        ZEND_ARG_INFO(0, host)
00186        ZEND_ARG_INFO(0, community)
00187        ZEND_ARG_INFO(0, object_id)
00188        ZEND_ARG_INFO(0, timeout)
00189        ZEND_ARG_INFO(0, retries)
00190 ZEND_END_ARG_INFO()
00191 
00192 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_walk, 0, 0, 3)
00193        ZEND_ARG_INFO(0, host)
00194        ZEND_ARG_INFO(0, community)
00195        ZEND_ARG_INFO(0, object_id)
00196        ZEND_ARG_INFO(0, timeout)
00197        ZEND_ARG_INFO(0, retries)
00198 ZEND_END_ARG_INFO()
00199 
00200 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_real_walk, 0, 0, 3)
00201        ZEND_ARG_INFO(0, host)
00202        ZEND_ARG_INFO(0, community)
00203        ZEND_ARG_INFO(0, object_id)
00204        ZEND_ARG_INFO(0, timeout)
00205        ZEND_ARG_INFO(0, retries)
00206 ZEND_END_ARG_INFO()
00207 
00208 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_set, 0, 0, 5)
00209        ZEND_ARG_INFO(0, host)
00210        ZEND_ARG_INFO(0, community)
00211        ZEND_ARG_INFO(0, object_id)
00212        ZEND_ARG_INFO(0, type)
00213        ZEND_ARG_INFO(0, value)
00214        ZEND_ARG_INFO(0, timeout)
00215        ZEND_ARG_INFO(0, retries)
00216 ZEND_END_ARG_INFO()
00217 
00218 ZEND_BEGIN_ARG_INFO_EX(arginfo_php_snmpv3, 0, 0, 2)
00219        ZEND_ARG_INFO(0, s)
00220        ZEND_ARG_INFO(0, st)
00221 ZEND_END_ARG_INFO()
00222 
00223 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_get, 0, 0, 8)
00224        ZEND_ARG_INFO(0, host)
00225        ZEND_ARG_INFO(0, sec_name)
00226        ZEND_ARG_INFO(0, sec_level)
00227        ZEND_ARG_INFO(0, auth_protocol)
00228        ZEND_ARG_INFO(0, auth_passphrase)
00229        ZEND_ARG_INFO(0, priv_protocol)
00230        ZEND_ARG_INFO(0, priv_passphrase)
00231        ZEND_ARG_INFO(0, object_id)
00232        ZEND_ARG_INFO(0, timeout)
00233        ZEND_ARG_INFO(0, retries)
00234 ZEND_END_ARG_INFO()
00235 
00236 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_getnext, 0, 0, 8)
00237        ZEND_ARG_INFO(0, host)
00238        ZEND_ARG_INFO(0, sec_name)
00239        ZEND_ARG_INFO(0, sec_level)
00240        ZEND_ARG_INFO(0, auth_protocol)
00241        ZEND_ARG_INFO(0, auth_passphrase)
00242        ZEND_ARG_INFO(0, priv_protocol)
00243        ZEND_ARG_INFO(0, priv_passphrase)
00244        ZEND_ARG_INFO(0, object_id)
00245        ZEND_ARG_INFO(0, timeout)
00246        ZEND_ARG_INFO(0, retries)
00247 ZEND_END_ARG_INFO()
00248 
00249 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_walk, 0, 0, 8)
00250        ZEND_ARG_INFO(0, host)
00251        ZEND_ARG_INFO(0, sec_name)
00252        ZEND_ARG_INFO(0, sec_level)
00253        ZEND_ARG_INFO(0, auth_protocol)
00254        ZEND_ARG_INFO(0, auth_passphrase)
00255        ZEND_ARG_INFO(0, priv_protocol)
00256        ZEND_ARG_INFO(0, priv_passphrase)
00257        ZEND_ARG_INFO(0, object_id)
00258        ZEND_ARG_INFO(0, timeout)
00259        ZEND_ARG_INFO(0, retries)
00260 ZEND_END_ARG_INFO()
00261 
00262 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_real_walk, 0, 0, 8)
00263        ZEND_ARG_INFO(0, host)
00264        ZEND_ARG_INFO(0, sec_name)
00265        ZEND_ARG_INFO(0, sec_level)
00266        ZEND_ARG_INFO(0, auth_protocol)
00267        ZEND_ARG_INFO(0, auth_passphrase)
00268        ZEND_ARG_INFO(0, priv_protocol)
00269        ZEND_ARG_INFO(0, priv_passphrase)
00270        ZEND_ARG_INFO(0, object_id)
00271        ZEND_ARG_INFO(0, timeout)
00272        ZEND_ARG_INFO(0, retries)
00273 ZEND_END_ARG_INFO()
00274 
00275 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_set, 0, 0, 10)
00276        ZEND_ARG_INFO(0, host)
00277        ZEND_ARG_INFO(0, sec_name)
00278        ZEND_ARG_INFO(0, sec_level)
00279        ZEND_ARG_INFO(0, auth_protocol)
00280        ZEND_ARG_INFO(0, auth_passphrase)
00281        ZEND_ARG_INFO(0, priv_protocol)
00282        ZEND_ARG_INFO(0, priv_passphrase)
00283        ZEND_ARG_INFO(0, object_id)
00284        ZEND_ARG_INFO(0, type)
00285        ZEND_ARG_INFO(0, value)
00286        ZEND_ARG_INFO(0, timeout)
00287        ZEND_ARG_INFO(0, retries)
00288 ZEND_END_ARG_INFO()
00289 
00290 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_valueretrieval, 0, 0, 1)
00291        ZEND_ARG_INFO(0, method)
00292 ZEND_END_ARG_INFO()
00293 
00294 ZEND_BEGIN_ARG_INFO(arginfo_snmp_get_valueretrieval, 0)
00295 ZEND_END_ARG_INFO()
00296 
00297 ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_read_mib, 0, 0, 1)
00298        ZEND_ARG_INFO(0, filename)
00299 ZEND_END_ARG_INFO()
00300 /* }}} */
00301 
00302 /* {{{ snmp_functions[]
00303  */
00304 const zend_function_entry snmp_functions[] = {
00305        PHP_FE(snmpget,                                         arginfo_snmpget)
00306        PHP_FE(snmpgetnext,                              arginfo_snmpgetnext)
00307        PHP_FE(snmpwalk,                                        arginfo_snmpwalk)
00308        PHP_FE(snmprealwalk,                                    arginfo_snmprealwalk)
00309        PHP_FALIAS(snmpwalkoid, snmprealwalk,     arginfo_snmprealwalk)
00310        PHP_FE(snmp_get_quick_print,                     arginfo_snmp_get_quick_print)
00311        PHP_FE(snmp_set_quick_print,                     arginfo_snmp_set_quick_print)
00312 #ifdef HAVE_NET_SNMP
00313        PHP_FE(snmp_set_enum_print,                      arginfo_snmp_set_enum_print)
00314        PHP_FE(snmp_set_oid_output_format,               arginfo_snmp_set_oid_output_format)
00315        PHP_FALIAS(snmp_set_oid_numeric_print, snmp_set_oid_output_format, arginfo_snmp_set_oid_output_format)
00316 #endif
00317        PHP_FE(snmpset,                           arginfo_snmpset)
00318 
00319        PHP_FE(snmp2_get,                         arginfo_snmp2_get)
00320        PHP_FE(snmp2_getnext,                     arginfo_snmp2_getnext)
00321        PHP_FE(snmp2_walk,                        arginfo_snmp2_walk)
00322        PHP_FE(snmp2_real_walk,            arginfo_snmp2_real_walk)
00323        PHP_FE(snmp2_set,                         arginfo_snmp2_set)
00324 
00325        PHP_FE(snmp3_get,                         arginfo_snmp3_get)
00326        PHP_FE(snmp3_getnext,                     arginfo_snmp3_getnext)
00327        PHP_FE(snmp3_walk,                        arginfo_snmp3_walk)
00328        PHP_FE(snmp3_real_walk,            arginfo_snmp3_real_walk)
00329        PHP_FE(snmp3_set,                         arginfo_snmp3_set)
00330        PHP_FE(snmp_set_valueretrieval, arginfo_snmp_set_valueretrieval)
00331        PHP_FE(snmp_get_valueretrieval, arginfo_snmp_get_valueretrieval)
00332 
00333        PHP_FE(snmp_read_mib,                     arginfo_snmp_read_mib)
00334        PHP_FE_END
00335 };
00336 /* }}} */
00337 
00338 #define SNMP_CMD_GET        1
00339 #define SNMP_CMD_GETNEXT    2
00340 #define SNMP_CMD_WALK              3
00341 #define SNMP_CMD_REALWALK   4
00342 #define SNMP_CMD_SET        11
00343 
00344 /* {{{ snmp_module_entry
00345  */
00346 zend_module_entry snmp_module_entry = {
00347        STANDARD_MODULE_HEADER,
00348        "snmp",
00349        snmp_functions,
00350        PHP_MINIT(snmp),
00351        PHP_MSHUTDOWN(snmp),
00352        NULL,
00353        NULL,
00354        PHP_MINFO(snmp),
00355        NO_VERSION_YET,
00356        PHP_MODULE_GLOBALS(snmp),
00357        PHP_GINIT(snmp),
00358        NULL,
00359        NULL,
00360        STANDARD_MODULE_PROPERTIES_EX
00361 };
00362 /* }}} */
00363 
00364 #ifdef COMPILE_DL_SNMP
00365 ZEND_GET_MODULE(snmp)
00366 #endif
00367 
00368 /* THREAD_LS snmp_module php_snmp_module; - may need one of these at some point */
00369 
00370 /* {{{ PHP_GINIT_FUNCTION
00371  */
00372 static PHP_GINIT_FUNCTION(snmp)
00373 {
00374        snmp_globals->valueretrieval = SNMP_VALUE_LIBRARY;
00375 }
00376 /* }}} */
00377 
00378 /* {{{ PHP_MINIT_FUNCTION
00379  */
00380 PHP_MINIT_FUNCTION(snmp)
00381 {
00382        init_snmp("snmpapp");
00383 
00384 #ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
00385        /* Prevent update of the snmpapp.conf file */
00386        netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
00387 #endif
00388 
00389 #ifdef HAVE_NET_SNMP
00390        REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_FULL", NETSNMP_OID_OUTPUT_FULL, CONST_CS | CONST_PERSISTENT);
00391        REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NUMERIC", NETSNMP_OID_OUTPUT_NUMERIC, CONST_CS | CONST_PERSISTENT);
00392 #endif
00393 
00394        REGISTER_LONG_CONSTANT("SNMP_VALUE_LIBRARY", SNMP_VALUE_LIBRARY, CONST_CS | CONST_PERSISTENT);
00395        REGISTER_LONG_CONSTANT("SNMP_VALUE_PLAIN", SNMP_VALUE_PLAIN, CONST_CS | CONST_PERSISTENT);
00396        REGISTER_LONG_CONSTANT("SNMP_VALUE_OBJECT", SNMP_VALUE_OBJECT, CONST_CS | CONST_PERSISTENT);
00397 
00398        REGISTER_LONG_CONSTANT("SNMP_BIT_STR", ASN_BIT_STR, CONST_CS | CONST_PERSISTENT);
00399        REGISTER_LONG_CONSTANT("SNMP_OCTET_STR", ASN_OCTET_STR, CONST_CS | CONST_PERSISTENT);
00400        REGISTER_LONG_CONSTANT("SNMP_OPAQUE", ASN_OPAQUE, CONST_CS | CONST_PERSISTENT);
00401        REGISTER_LONG_CONSTANT("SNMP_NULL", ASN_NULL, CONST_CS | CONST_PERSISTENT);
00402        REGISTER_LONG_CONSTANT("SNMP_OBJECT_ID", ASN_OBJECT_ID, CONST_CS | CONST_PERSISTENT);
00403        REGISTER_LONG_CONSTANT("SNMP_IPADDRESS", ASN_IPADDRESS, CONST_CS | CONST_PERSISTENT);
00404        REGISTER_LONG_CONSTANT("SNMP_COUNTER", ASN_GAUGE, CONST_CS | CONST_PERSISTENT);
00405        REGISTER_LONG_CONSTANT("SNMP_UNSIGNED", ASN_UNSIGNED, CONST_CS | CONST_PERSISTENT);
00406        REGISTER_LONG_CONSTANT("SNMP_TIMETICKS", ASN_TIMETICKS, CONST_CS | CONST_PERSISTENT);
00407        REGISTER_LONG_CONSTANT("SNMP_UINTEGER", ASN_UINTEGER, CONST_CS | CONST_PERSISTENT);
00408        REGISTER_LONG_CONSTANT("SNMP_INTEGER", ASN_INTEGER, CONST_CS | CONST_PERSISTENT);
00409        REGISTER_LONG_CONSTANT("SNMP_COUNTER64", ASN_COUNTER64, CONST_CS | CONST_PERSISTENT);
00410 
00411        return SUCCESS;
00412 }
00413 /* }}} */
00414 
00415 /* {{{ PHP_MSHUTDOWN_FUNCTION
00416  */
00417 PHP_MSHUTDOWN_FUNCTION(snmp)
00418 {
00419        snmp_shutdown("snmpapp");
00420 
00421        return SUCCESS;
00422 }
00423 /* }}} */
00424 
00425 /* {{{ PHP_MINFO_FUNCTION
00426  */
00427 PHP_MINFO_FUNCTION(snmp)
00428 {
00429        php_info_print_table_start();
00430 #ifdef HAVE_NET_SNMP
00431        php_info_print_table_row(2, "NET-SNMP Support", "enabled");
00432        php_info_print_table_row(2, "NET-SNMP Version", netsnmp_get_version());
00433 #else
00434        php_info_print_table_row(2, "UCD-SNMP Support", "enabled");
00435        php_info_print_table_row(2, "UCD-SNMP Version", VersionInfo);
00436 #endif
00437        php_info_print_table_end();
00438 }
00439 /* }}} */
00440 
00441 static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_DC)
00442 {
00443        zval *val;
00444 #if I64CHARSZ > 2047
00445        char buf[I64CHARSZ + 1];
00446 #else
00447        char buf[2048];
00448 #endif
00449 
00450        buf[0] = 0;
00451 
00452        if (SNMP_G(valueretrieval) == SNMP_VALUE_LIBRARY) {
00453 #ifdef HAVE_NET_SNMP
00454               snprint_value(buf, sizeof(buf), vars->name, vars->name_length, vars);
00455 #else
00456               sprint_value(buf,vars->name, vars->name_length, vars);
00457 #endif
00458               ZVAL_STRING(snmpval, buf, 1);
00459               return;
00460        }
00461 
00462        MAKE_STD_ZVAL(val);
00463 
00464        switch (vars->type) {
00465        case ASN_BIT_STR:           /* 0x03, asn1.h */
00466               ZVAL_STRINGL(val, vars->val.bitstring, vars->val_len, 1);
00467               break;
00468 
00469        case ASN_OCTET_STR:         /* 0x04, asn1.h */
00470        case ASN_OPAQUE:            /* 0x44, snmp_impl.h */
00471               ZVAL_STRINGL(val, vars->val.string, vars->val_len, 1);
00472               break;
00473 
00474        case ASN_NULL:                     /* 0x05, asn1.h */
00475               ZVAL_NULL(val);
00476               break;
00477 
00478        case ASN_OBJECT_ID:         /* 0x06, asn1.h */
00479 #ifdef HAVE_NET_SNMP
00480               snprint_objid(buf, sizeof(buf), vars->val.objid, vars->val_len / sizeof(oid));
00481 #else
00482               sprint_objid(buf, vars->val.objid, vars->val_len / sizeof(oid));
00483 #endif
00484 
00485               ZVAL_STRING(val, buf, 1);
00486               break;
00487 
00488        case ASN_IPADDRESS:         /* 0x40, snmp_impl.h */
00489               snprintf(buf, sizeof(buf)-1, "%d.%d.%d.%d",
00490                        (vars->val.string)[0], (vars->val.string)[1],
00491                        (vars->val.string)[2], (vars->val.string)[3]);
00492               buf[sizeof(buf)-1]=0;
00493               ZVAL_STRING(val, buf, 1);
00494               break;
00495 
00496        case ASN_COUNTER:           /* 0x41, snmp_impl.h */
00497        case ASN_GAUGE:                    /* 0x42, snmp_impl.h */
00498        /* ASN_UNSIGNED is the same as ASN_GAUGE */
00499        case ASN_TIMETICKS:         /* 0x43, snmp_impl.h */
00500        case ASN_UINTEGER:          /* 0x47, snmp_impl.h */
00501               snprintf(buf, sizeof(buf)-1, "%lu", *vars->val.integer);
00502               buf[sizeof(buf)-1]=0;
00503               ZVAL_STRING(val, buf, 1);
00504               break;
00505 
00506        case ASN_INTEGER:           /* 0x02, asn1.h */
00507               snprintf(buf, sizeof(buf)-1, "%ld", *vars->val.integer);
00508               buf[sizeof(buf)-1]=0;
00509               ZVAL_STRING(val, buf, 1);
00510               break;
00511 
00512        case ASN_COUNTER64:         /* 0x46, snmp_impl.h */
00513               printU64(buf, vars->val.counter64);
00514               ZVAL_STRING(val, buf, 1);
00515               break;
00516 
00517        default:
00518               ZVAL_STRING(val, "Unknown value type", 1);
00519               break;
00520        }
00521 
00522        if (SNMP_G(valueretrieval) == SNMP_VALUE_PLAIN) {
00523               *snmpval = *val;
00524               zval_copy_ctor(snmpval);
00525        } else {
00526               object_init(snmpval);
00527               add_property_long(snmpval, "type", vars->type);
00528               add_property_zval(snmpval, "value", val);
00529        }
00530 }
00531 
00532 /* {{{ php_snmp_internal
00533 *
00534 * Generic SNMP object fetcher (for all SNMP versions)
00535 *
00536 * st=SNMP_CMD_GET   get - query an agent with SNMP-GET.
00537 * st=SNMP_CMD_GETNEXT   getnext - query an agent with SNMP-GETNEXT.
00538 * st=SNMP_CMD_WALK   walk - walk the mib and return a single dimensional array 
00539 *          containing the values.
00540 * st=SNMP_CMD_REALWALK   realwalk() and walkoid() - walk the mib and return an 
00541 *          array of oid,value pairs.
00542 * st=SNMP_CMD_SET  set() - query an agent and set a single value
00543 *
00544 */
00545 static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, 
00546                                                  struct snmp_session *session,
00547                                                  char *objid,
00548                                                  char type,
00549                                                  char* value) 
00550 {
00551        struct snmp_session *ss;
00552        struct snmp_pdu *pdu=NULL, *response;
00553        struct variable_list *vars;
00554        oid name[MAX_NAME_LEN];
00555        size_t name_length;
00556        oid root[MAX_NAME_LEN];
00557        size_t rootlen = 0;
00558        int gotroot = 0;
00559        int status, count;
00560        char buf[2048];
00561        char buf2[2048];
00562        int keepwalking=1;
00563        char *err;
00564        zval *snmpval = NULL;
00565 
00566        if (st >= SNMP_CMD_WALK) { /* walk */
00567               rootlen = MAX_NAME_LEN;
00568               if (strlen(objid)) { /* on a walk, an empty string means top of tree - no error */
00569                      if (snmp_parse_oid(objid, root, &rootlen)) {
00570                             gotroot = 1;
00571                      } else {
00572                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid);
00573                      }
00574               }
00575 
00576               if (!gotroot) {
00577                      memmove((char *) root, (char *) objid_mib, sizeof(objid_mib));
00578                      rootlen = sizeof(objid_mib) / sizeof(oid);
00579                      gotroot = 1;
00580               }
00581        }
00582 
00583        if ((ss = snmp_open(session)) == NULL) {
00584               snmp_error(session, NULL, NULL, &err);
00585               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open snmp connection: %s", err);
00586               free(err);
00587               RETURN_FALSE;
00588        }
00589 
00590        if (st >= SNMP_CMD_WALK) {
00591               memmove((char *)name, (char *)root, rootlen * sizeof(oid));
00592               name_length = rootlen;
00593               switch(st) {
00594                      case SNMP_CMD_WALK:
00595                      case SNMP_CMD_REALWALK:
00596                             array_init(return_value);
00597                             break;
00598                      default:
00599                             RETVAL_TRUE;
00600                             break;
00601               }
00602        }
00603 
00604        while (keepwalking) {
00605               keepwalking = 0;
00606               if ((st == SNMP_CMD_GET) || (st == SNMP_CMD_GETNEXT)) {
00607                      name_length = MAX_OID_LEN;
00608                      if (!snmp_parse_oid(objid, name, &name_length)) {
00609                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid);
00610                             snmp_close(ss);
00611                             RETURN_FALSE;
00612                      }
00613                      pdu = snmp_pdu_create((st == SNMP_CMD_GET) ? SNMP_MSG_GET : SNMP_MSG_GETNEXT);
00614                      snmp_add_null_var(pdu, name, name_length);
00615               } else if (st == SNMP_CMD_SET) {
00616                      pdu = snmp_pdu_create(SNMP_MSG_SET);
00617                      if (snmp_add_var(pdu, name, name_length, type, value)) {
00618 #ifdef HAVE_NET_SNMP
00619                             snprint_objid(buf, sizeof(buf), name, name_length);
00620 #else
00621                             sprint_objid(buf, name, name_length);
00622 #endif
00623                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not add variable: %s %c %s", buf, type, value);
00624                             snmp_free_pdu(pdu);
00625                             snmp_close(ss);
00626                             RETURN_FALSE;
00627                      }
00628               } else if (st >= SNMP_CMD_WALK) {
00629                      if (session->version == SNMP_VERSION_1) {
00630                             pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
00631                      } else {
00632                             pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
00633                             pdu->non_repeaters = 0;
00634                             pdu->max_repetitions = 20;
00635                      }
00636                      snmp_add_null_var(pdu, name, name_length);
00637               }
00638 
00639 retry:
00640               status = snmp_synch_response(ss, pdu, &response);
00641               if (status == STAT_SUCCESS) {
00642                      if (response->errstat == SNMP_ERR_NOERROR) {
00643                             for (vars = response->variables; vars; vars = vars->next_variable) {
00644                                    if (st >= SNMP_CMD_WALK && st != SNMP_CMD_SET && 
00645                                           (vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid)))) {
00646                                           continue;       /* not part of this subtree */
00647                                    }
00648 
00649                                    if (st != SNMP_CMD_SET) {
00650                                           MAKE_STD_ZVAL(snmpval);
00651                                           php_snmp_getvalue(vars, snmpval TSRMLS_CC);
00652                                    }
00653 
00654                                    if (st == SNMP_CMD_GET) {
00655                                           *return_value = *snmpval;
00656                                           zval_copy_ctor(return_value);
00657                                           zval_ptr_dtor(&snmpval);
00658                                           snmp_free_pdu(response);
00659                                           snmp_close(ss);
00660                                           return;
00661                                    } else if (st == SNMP_CMD_GETNEXT) {
00662                                           *return_value = *snmpval;
00663                                           zval_copy_ctor(return_value);
00664                                           snmp_free_pdu(response);
00665                                           snmp_close(ss);
00666                                           return;
00667                                    } else if (st == SNMP_CMD_WALK) {
00668                                           add_next_index_zval(return_value,snmpval); /* Add to returned array */
00669                                    } else if (st == SNMP_CMD_REALWALK && vars->type != SNMP_ENDOFMIBVIEW && vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) {
00670 #ifdef HAVE_NET_SNMP
00671                                           snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
00672 #else
00673                                           sprint_objid(buf2, vars->name, vars->name_length);
00674 #endif
00675                                           add_assoc_zval(return_value,buf2,snmpval);
00676                                    }
00677                                    if (st >= SNMP_CMD_WALK && st != SNMP_CMD_SET) {
00678                                           if (vars->type != SNMP_ENDOFMIBVIEW && 
00679                                                  vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) {
00680                                                  if (snmp_oid_compare(name, name_length, vars->name, vars->name_length) >= 0) {
00681                                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error: OID not increasing: %s",name);
00682                                                         keepwalking = 0;
00683                                                  } else {
00684                                                         memmove((char *)name, (char *)vars->name,vars->name_length * sizeof(oid));
00685                                                         name_length = vars->name_length;
00686                                                         keepwalking = 1;
00687                                                  }
00688                                           }
00689                                    }
00690                             }      
00691                      } else {
00692                             if ((st != SNMP_CMD_WALK && st != SNMP_CMD_REALWALK) || response->errstat != SNMP_ERR_NOSUCHNAME) {
00693                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error in packet: %s", snmp_errstring(response->errstat));
00694                                    if (response->errstat == SNMP_ERR_NOSUCHNAME) {
00695                                           for (count=1, vars = response->variables; vars && count != response->errindex;
00696                                           vars = vars->next_variable, count++);
00697                                           if (vars) {
00698 #ifdef HAVE_NET_SNMP
00699                                                  snprint_objid(buf, sizeof(buf), vars->name, vars->name_length);
00700 #else
00701                                                  sprint_objid(buf,vars->name, vars->name_length);
00702 #endif
00703                                           }
00704                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "This name does not exist: %s",buf);
00705                                    }
00706                                    if (st == SNMP_CMD_GET) {
00707                                           if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GET)) != NULL) {
00708                                                  snmp_free_pdu(response);
00709                                                  goto retry;
00710                                           }
00711                                    } else if (st == SNMP_CMD_SET) {
00712                                           if ((pdu = snmp_fix_pdu(response, SNMP_MSG_SET)) != NULL) {
00713                                                  snmp_free_pdu(response);
00714                                                  goto retry;
00715                                           }
00716                                    } else if (st == SNMP_CMD_GETNEXT) {
00717                                           if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) != NULL) {
00718                                                  snmp_free_pdu(response);
00719                                                  goto retry;
00720                                           }
00721                                    } else if (st >= SNMP_CMD_WALK) { /* Here we do walks. */
00722                                           if ((pdu = snmp_fix_pdu(response, ((session->version == SNMP_VERSION_1)
00723                                                                       ? SNMP_MSG_GETNEXT
00724                                                                       : SNMP_MSG_GETBULK))) != NULL) {
00725                                                  snmp_free_pdu(response);
00726                                                  goto retry;
00727                                           }
00728                                    }
00729                                    snmp_free_pdu(response);
00730                                    snmp_close(ss);
00731                                    if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
00732                                           zval_dtor(return_value);
00733                                    }
00734                                    RETURN_FALSE;
00735                             }
00736                      }
00737               } else if (status == STAT_TIMEOUT) {
00738                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "No response from %s", session->peername);
00739                      if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
00740                             zval_dtor(return_value);
00741                      }
00742                      snmp_close(ss);
00743                      RETURN_FALSE;
00744               } else {    /* status == STAT_ERROR */
00745                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred, quitting");
00746                      if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
00747                             zval_dtor(return_value);
00748                      }
00749                      snmp_close(ss);
00750                      RETURN_FALSE;
00751               }
00752               if (response) {
00753                      snmp_free_pdu(response);
00754               }
00755        } /* keepwalking */
00756        snmp_close(ss);
00757 }
00758 /* }}} */
00759 
00760 /* {{{ php_snmp
00761 *
00762 * Generic community based SNMP handler for version 1 and 2.
00763 * This function makes use of the internal SNMP object fetcher.
00764 * The object fetcher is shared with SNMPv3.
00765 *
00766 * st=SNMP_CMD_GET   get - query an agent with SNMP-GET.
00767 * st=SNMP_CMD_GETNEXT   getnext - query an agent with SNMP-GETNEXT.
00768 * st=SNMP_CMD_WALK   walk - walk the mib and return a single dimensional array 
00769 *          containing the values.
00770 * st=SNMP_CMD_REALWALK   realwalk() and walkoid() - walk the mib and return an 
00771 *          array of oid,value pairs.
00772 * st=5-8 ** Reserved **
00773 * st=SNMP_CMD_SET  set() - query an agent and set a single value
00774 *
00775 */
00776 static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) 
00777 {
00778        char *a1, *a2, *a3;
00779        int a1_len, a2_len, a3_len;
00780        struct snmp_session session;
00781        long timeout = SNMP_DEFAULT_TIMEOUT;
00782        long retries = SNMP_DEFAULT_RETRIES;
00783        char type = (char) 0;
00784        char *value = (char *) 0, *stype = "";
00785        int value_len, stype_len;
00786        char hostname[MAX_NAME_LEN];
00787        int remote_port = 161;
00788        char *pptr;
00789        int argc = ZEND_NUM_ARGS();
00790 
00791        if (st == SNMP_CMD_SET) {
00792               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) {
00793                      return;
00794               }
00795        } else {
00796               /* SNMP_CMD_GET
00797                * SNMP_CMD_GETNEXT
00798                * SNMP_CMD_WALK
00799                * SNMP_CMD_REALWALK
00800                */
00801               if (zend_parse_parameters(argc TSRMLS_CC, "sss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len, &timeout, &retries) == FAILURE) {
00802                      return;
00803               }
00804        }
00805        
00806        if (st == SNMP_CMD_SET) {
00807               type = stype[0];
00808        } 
00809 
00810        snmp_sess_init(&session);
00811        strlcpy(hostname, a1, sizeof(hostname));
00812        if ((pptr = strchr (hostname, ':'))) {
00813               remote_port = strtol (pptr + 1, NULL, 0);
00814        }
00815 
00816        session.peername = hostname;
00817        session.remote_port = remote_port;
00818        session.version = version;
00819        /*
00820        * FIXME: potential memory leak
00821        * This is a workaround for an "artifact" (Mike Slifcak)
00822        * in (at least) ucd-snmp 3.6.1 which frees
00823        * memory it did not allocate
00824        */
00825 #ifdef UCD_SNMP_HACK
00826        session.community = (u_char *)strdup(a2); /* memory freed by SNMP library, strdup NOT estrdup */
00827 #else
00828        session.community = (u_char *)a2;
00829 #endif
00830        session.community_len = a2_len;
00831        session.retries = retries;
00832        session.timeout = timeout;
00833        
00834        session.authenticator = NULL;
00835 
00836        php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session, a3, type, value);
00837 }
00838 /* }}} */
00839 
00840 /* {{{ proto string snmpget(string host, string community, string object_id [, int timeout [, int retries]]) 
00841    Fetch a SNMP object */
00842 PHP_FUNCTION(snmpget)
00843 {
00844        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_1);
00845 }
00846 /* }}} */
00847 
00848 /* {{{ proto string snmpgetnext(string host, string community, string object_id [, int timeout [, int retries]]) 
00849    Fetch a SNMP object */
00850 PHP_FUNCTION(snmpgetnext)
00851 {
00852        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_1);
00853 }
00854 /* }}} */
00855 
00856 /* {{{ proto array snmpwalk(string host, string community, string object_id [, int timeout [, int retries]]) 
00857    Return all objects under the specified object id */
00858 PHP_FUNCTION(snmpwalk)
00859 {
00860        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_1);
00861 }
00862 /* }}} */
00863 
00864 /* {{{ proto array snmprealwalk(string host, string community, string object_id [, int timeout [, int retries]])
00865    Return all objects including their respective object id withing the specified one */
00866 PHP_FUNCTION(snmprealwalk)
00867 {
00868        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_1);
00869 }
00870 /* }}} */
00871 
00872 /* {{{ proto bool snmp_get_quick_print(void)
00873    Return the current status of quick_print */
00874 PHP_FUNCTION(snmp_get_quick_print)
00875 {
00876        if (zend_parse_parameters_none() == FAILURE) {
00877               return;
00878        }
00879 
00880 #ifdef HAVE_NET_SNMP
00881        RETURN_BOOL(netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT));
00882 #else
00883        RETURN_BOOL(snmp_get_quick_print());
00884 #endif
00885 }
00886 /* }}} */
00887 
00888 /* {{{ proto void snmp_set_quick_print(int quick_print)
00889    Return all objects including their respective object id withing the specified one */
00890 PHP_FUNCTION(snmp_set_quick_print)
00891 {
00892        long a1;
00893 
00894        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
00895               return;
00896        }
00897 
00898 #ifdef HAVE_NET_SNMP
00899        netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, (int) a1);
00900 #else
00901        snmp_set_quick_print((int)a1);
00902 #endif
00903 }
00904 /* }}} */
00905 
00906 #ifdef HAVE_NET_SNMP
00907 /* {{{ proto void snmp_set_enum_print(int enum_print)
00908    Return all values that are enums with their enum value instead of the raw integer */
00909 PHP_FUNCTION(snmp_set_enum_print)
00910 {
00911        long a1;
00912 
00913        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
00914               return;
00915        }
00916 
00917        netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, (int) a1);
00918 } 
00919 /* }}} */
00920 
00921 /* {{{ proto void snmp_set_oid_output_format(int oid_format)
00922    Set the OID output format. */
00923 PHP_FUNCTION(snmp_set_oid_output_format)
00924 {
00925        long a1;
00926 
00927        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
00928               return;
00929        }
00930 
00931        switch ((int) a1) {
00932               case 0:
00933               case NETSNMP_OID_OUTPUT_FULL:
00934                      a1 = NETSNMP_OID_OUTPUT_FULL;
00935                      break;
00936 
00937               default:
00938               case NETSNMP_OID_OUTPUT_NUMERIC:
00939                      a1 = NETSNMP_OID_OUTPUT_NUMERIC;
00940                      break;
00941        }
00942 
00943        netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, a1);
00944 } 
00945 /* }}} */
00946 #endif
00947 
00948 /* {{{ proto int snmpset(string host, string community, string object_id, string type, mixed value [, int timeout [, int retries]]) 
00949    Set the value of a SNMP object */
00950 PHP_FUNCTION(snmpset)
00951 {
00952        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_SET, SNMP_VERSION_1);
00953 }
00954 /* }}} */
00955 
00956 /* {{{ int netsnmp_session_set_sec_name(struct snmp_session *s, char *name)
00957    Set the security name in the snmpv3 session */
00958 static int netsnmp_session_set_sec_name(struct snmp_session *s, char *name)
00959 {
00960        if ((s) && (name)) {
00961               s->securityName = strdup(name);
00962               s->securityNameLen = strlen(s->securityName);
00963               return (0);
00964        }
00965        return (-1);
00966 }
00967 /* }}} */
00968 
00969 /* {{{ int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
00970    Set the security level in the snmpv3 session */
00971 static int netsnmp_session_set_sec_level(struct snmp_session *s, char *level TSRMLS_DC)
00972 {
00973        if ((s) && (level)) {
00974               if (!strcasecmp(level, "noAuthNoPriv") || !strcasecmp(level, "nanp")) {
00975                      s->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
00976                      return (0);
00977               } else if (!strcasecmp(level, "authNoPriv") || !strcasecmp(level, "anp")) {
00978                      s->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
00979                      return (0);
00980               } else if (!strcasecmp(level, "authPriv") || !strcasecmp(level, "ap")) {
00981                      s->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
00982                      return (0);
00983               }
00984        }
00985        return (-1);
00986 }
00987 /* }}} */
00988 
00989 /* {{{ int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot)
00990    Set the authentication protocol in the snmpv3 session */
00991 static int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
00992 {
00993        if ((s) && (prot)) {
00994               if (!strcasecmp(prot, "MD5")) {
00995                      s->securityAuthProto = usmHMACMD5AuthProtocol;
00996                      s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
00997                      return (0);
00998               } else if (!strcasecmp(prot, "SHA")) {
00999                      s->securityAuthProto = usmHMACSHA1AuthProtocol;
01000                      s->securityAuthProtoLen = OIDSIZE(usmHMACSHA1AuthProtocol);
01001                      return (0);
01002               }
01003        }
01004        return (-1);
01005 }
01006 /* }}} */
01007 
01008 /* {{{ int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot)
01009    Set the security protocol in the snmpv3 session */
01010 static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
01011 {
01012        if ((s) && (prot)) {
01013               if (!strcasecmp(prot, "DES")) {
01014                      s->securityPrivProto = usmDESPrivProtocol;
01015                      s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
01016                      return (0);
01017 #ifdef HAVE_AES
01018               } else if (!strcasecmp(prot, "AES128")
01019 #ifdef SNMP_VALIDATE_ERR
01020 /* 
01021 * In Net-SNMP before 5.2, the following symbols exist:
01022 * usmAES128PrivProtocol, usmAES192PrivProtocol, usmAES256PrivProtocol
01023 * In an effort to be more standards-compliant, 5.2 removed the last two.
01024 * As of 5.2, the symbols are:
01025 * usmAESPrivProtocol, usmAES128PrivProtocol
01026 * 
01027 * As we want this extension to compile on both versions, we use the latter
01028 * symbol on purpose, as it's defined to be the same as the former.
01029 *
01030 * However, in 5.2 the type of usmAES128PrivProtocol is a pointer, not an
01031 * array, so we cannot use the OIDSIZE macro because it uses sizeof().
01032 *
01033 */
01034                      || !strcasecmp(prot, "AES")) {
01035                      s->securityPrivProto = usmAES128PrivProtocol;
01036                      s->securityPrivProtoLen = USM_PRIV_PROTO_AES128_LEN;
01037                      return (0);
01038 #else                
01039               ) {
01040                      s->securityPrivProto = usmAES128PrivProtocol;
01041                      s->securityPrivProtoLen = OIDSIZE(usmAES128PrivProtocol);
01042                      return (0);
01043               } else if (!strcasecmp(prot, "AES192")) {
01044                      s->securityPrivProto = usmAES192PrivProtocol;
01045                      s->securityPrivProtoLen = OIDSIZE(usmAES192PrivProtocol);
01046                      return (0);
01047               } else if (!strcasecmp(prot, "AES256")) {
01048                      s->securityPrivProto = usmAES256PrivProtocol;
01049                      s->securityPrivProtoLen = OIDSIZE(usmAES256PrivProtocol);
01050                      return (0);
01051 #endif
01052 #endif
01053               }
01054        }
01055        return (-1);
01056 }
01057 /* }}} */
01058 
01059 /* {{{ int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass)
01060    Make key from pass phrase in the snmpv3 session */
01061 static int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass TSRMLS_DC)
01062 {
01063        /*
01064         * make master key from pass phrases 
01065         */
01066        if ((s) && (pass) && strlen(pass)) {
01067               s->securityAuthKeyLen = USM_AUTH_KU_LEN;
01068               if (s->securityAuthProto == NULL) {
01069                      /* get .conf set default */
01070                      const oid *def = get_default_authtype(&(s->securityAuthProtoLen));
01071                      s->securityAuthProto = snmp_duplicate_objid(def, s->securityAuthProtoLen);
01072               }
01073               if (s->securityAuthProto == NULL) {
01074                      /* assume MD5 */
01075                      s->securityAuthProto =
01076                             snmp_duplicate_objid(usmHMACMD5AuthProtocol, OIDSIZE(usmHMACMD5AuthProtocol));
01077                      s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
01078               }
01079               if (generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
01080                             (u_char *) pass, strlen(pass),
01081                             s->securityAuthKey, &(s->securityAuthKeyLen)) != SNMPERR_SUCCESS) {
01082                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for authentication pass phrase");
01083                      return (-2);
01084               }
01085               return (0);
01086        }
01087        return (-1);
01088 }
01089 /* }}} */
01090 
01091 /* {{{ int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass)
01092    Make key from pass phrase in the snmpv3 session */
01093 static int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass TSRMLS_DC)
01094 {
01095        if ((s) && (pass) && strlen(pass)) {
01096               s->securityPrivKeyLen = USM_PRIV_KU_LEN;
01097               if (s->securityPrivProto == NULL) {
01098                      /* get .conf set default */
01099                      const oid *def = get_default_privtype(&(s->securityPrivProtoLen));
01100                      s->securityPrivProto = snmp_duplicate_objid(def, s->securityPrivProtoLen);
01101               }
01102               if (s->securityPrivProto == NULL) {
01103                      /* assume DES */
01104                      s->securityPrivProto = snmp_duplicate_objid(usmDESPrivProtocol,
01105                             OIDSIZE(usmDESPrivProtocol));
01106                      s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
01107               }
01108               if (generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
01109                             pass, strlen(pass),
01110                             s->securityPrivKey, &(s->securityPrivKeyLen)) != SNMPERR_SUCCESS) {
01111                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for privacy pass phrase");
01112                      return (-2);
01113               }
01114               return (0);
01115        }
01116        return (-1);
01117 }
01118 /* }}} */
01119 
01120 /* {{{ proto string snmp2_get(string host, string community, string object_id [, int timeout [, int retries]]) 
01121    Fetch a SNMP object */
01122 PHP_FUNCTION(snmp2_get)
01123 {
01124        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_2c);
01125 }
01126 /* }}} */
01127 
01128 /* {{{ proto string snmp2_getnext(string host, string community, string object_id [, int timeout [, int retries]]) 
01129    Fetch a SNMP object */
01130 PHP_FUNCTION(snmp2_getnext)
01131 {
01132        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_2c);
01133 }
01134 /* }}} */
01135 
01136 /* {{{ proto array snmp2_walk(string host, string community, string object_id [, int timeout [, int retries]]) 
01137    Return all objects under the specified object id */
01138 PHP_FUNCTION(snmp2_walk)
01139 {
01140        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_2c);
01141 }
01142 /* }}} */
01143 
01144 /* {{{ proto array snmp2_real_walk(string host, string community, string object_id [, int timeout [, int retries]])
01145    Return all objects including their respective object id withing the specified one */
01146 PHP_FUNCTION(snmp2_real_walk)
01147 {
01148        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_2c);
01149 }
01150 /* }}} */
01151 
01152 /* {{{ proto int snmp2_set(string host, string community, string object_id, string type, mixed value [, int timeout [, int retries]]) 
01153    Set the value of a SNMP object */
01154 PHP_FUNCTION(snmp2_set)
01155 {
01156        php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_SET, SNMP_VERSION_2c);
01157 }
01158 /* }}} */
01159 
01160 /* {{{ proto void php_snmpv3(INTERNAL_FUNCTION_PARAMETERS, int st)
01161 *
01162 * Generic SNMPv3 object fetcher
01163 * From here is passed on the common internal object fetcher.
01164 *
01165 * st=SNMP_CMD_GET   snmp3_get() - query an agent and return a single value.
01166 * st=SNMP_CMD_GETNEXT   snmp3_getnext() - query an agent and return the next single value.
01167 * st=SNMP_CMD_WALK   snmp3_walk() - walk the mib and return a single dimensional array 
01168 *                       containing the values.
01169 * st=SNMP_CMD_REALWALK   snmp3_real_walk() - walk the mib and return an 
01170 *                            array of oid,value pairs.
01171 * st=SNMP_CMD_SET  snmp3_set() - query an agent and set a single value
01172 *
01173 */
01174 static void php_snmpv3(INTERNAL_FUNCTION_PARAMETERS, int st)
01175 {
01176        char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
01177        int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len, a8_len;
01178        struct snmp_session session;
01179        long timeout = SNMP_DEFAULT_TIMEOUT;
01180        long retries = SNMP_DEFAULT_RETRIES;
01181        char type = (char) 0;
01182        char *value = (char *) 0, *stype = "";
01183        int stype_len, value_len;   
01184        char hostname[MAX_NAME_LEN];
01185        int remote_port = 161;
01186        char *pptr;
01187        int argc = ZEND_NUM_ARGS();
01188        
01189        if (st == SNMP_CMD_SET) {   
01190               if (zend_parse_parameters(argc TSRMLS_CC, "ssssssssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
01191                      &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &a8, &a8_len, &stype, &stype_len, &value, &value_len, &timeout, &retries) == FAILURE) {
01192                      return;
01193               }
01194        } else {
01195               /* SNMP_CMD_GET
01196                * SNMP_CMD_GETNEXT
01197                * SNMP_CMD_WALK
01198                * SNMP_CMD_REALWALK
01199                */
01200               if (zend_parse_parameters(argc TSRMLS_CC, "ssssssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
01201                      &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &a8, &a8_len, &timeout, &retries) == FAILURE) {
01202                      return;
01203               }
01204        }
01205 
01206        snmp_sess_init(&session);
01207        /* This is all SNMPv3 */
01208        session.version = SNMP_VERSION_3;
01209 
01210        /* Reading the hostname and its optional non-default port number */
01211        strlcpy(hostname, a1, sizeof(hostname));
01212        if ((pptr = strchr(hostname, ':'))) {
01213               remote_port = strtol(pptr + 1, NULL, 0);
01214        }
01215        session.peername = hostname;
01216        session.remote_port = remote_port;
01217 
01218        /* Setting the security name. */
01219        if (netsnmp_session_set_sec_name(&session, a2)) {
01220               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could net set security name: %s", a2);
01221               RETURN_FALSE;
01222        }
01223 
01224        /* Setting the security level. */
01225        if (netsnmp_session_set_sec_level(&session, a3 TSRMLS_CC)) {
01226               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security level: %s", a3);
01227               RETURN_FALSE;
01228        }
01229 
01230        /* Setting the authentication protocol. */
01231        if (netsnmp_session_set_auth_protocol(&session, a4 TSRMLS_CC)) {
01232               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid authentication protocol: %s", a4);
01233               RETURN_FALSE;
01234        }
01235 
01236        /* Setting the authentication passphrase. */
01237        if (netsnmp_session_gen_auth_key(&session, a5 TSRMLS_CC)) {
01238               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not generate key for authentication pass phrase: %s", a5);
01239               RETURN_FALSE;
01240        }
01241 
01242        /* Setting the security protocol. */
01243        if (netsnmp_session_set_sec_protocol(&session, a6 TSRMLS_CC) && a6_len) {
01244               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security protocol: %s", a6);
01245               RETURN_FALSE;
01246        }
01247 
01248        /* Setting the security protocol passphrase. */
01249        if (netsnmp_session_gen_sec_key(&session, a7 TSRMLS_CC) && a7_len) {
01250               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not generate key for security pass phrase: %s", a7);
01251               RETURN_FALSE;
01252        }
01253 
01254        if (st == SNMP_CMD_SET) {
01255               type = stype[0];
01256        }
01257 
01258        session.retries = retries;
01259        session.timeout = timeout;
01260 
01261        php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session, a8, type, value);
01262 }
01263 /* }}} */
01264 
01265 /* {{{ 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]])
01266    Fetch the value of a SNMP object */
01267 PHP_FUNCTION(snmp3_get)
01268 {
01269        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET);
01270 }
01271 /* }}} */
01272 
01273 /* {{{ 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]])
01274    Fetch the value of a SNMP object */
01275 PHP_FUNCTION(snmp3_getnext)
01276 {
01277        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT);
01278 }
01279 /* }}} */
01280 
01281 /* {{{ 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]])
01282    Fetch the value of a SNMP object */
01283 PHP_FUNCTION(snmp3_walk)
01284 {
01285        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK);
01286 }
01287 /* }}} */
01288 
01289 /* {{{ 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]])
01290    Fetch the value of a SNMP object */
01291 PHP_FUNCTION(snmp3_real_walk)
01292 {
01293        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_REALWALK);
01294 }
01295 /* }}} */
01296 
01297 /* {{{ 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]])
01298    Fetch the value of a SNMP object */
01299 PHP_FUNCTION(snmp3_set)
01300 {
01301        php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET);
01302 }
01303 /* }}} */
01304 
01305 /* {{{ proto void snmp_set_valueretrieval(int method)
01306    Specify the method how the SNMP values will be returned */
01307 PHP_FUNCTION(snmp_set_valueretrieval)
01308 {
01309        long method;
01310 
01311        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
01312               return;
01313        }
01314 
01315        if ((method == SNMP_VALUE_LIBRARY) || (method == SNMP_VALUE_PLAIN) || (method == SNMP_VALUE_OBJECT)) {
01316               SNMP_G(valueretrieval) = method;
01317        }
01318 }
01319 /* }}} */
01320 
01321 /* {{{ proto int snmp_get_valueretrieval()
01322    Return the method how the SNMP values will be returned */
01323 PHP_FUNCTION(snmp_get_valueretrieval)
01324 {
01325        RETURN_LONG(SNMP_G(valueretrieval));
01326 }
01327 /* }}} */
01328 
01329 /* {{{ proto int snmp_read_mib(string filename)
01330    Reads and parses a MIB file into the active MIB tree. */
01331 PHP_FUNCTION(snmp_read_mib)
01332 {
01333        char *filename;
01334        int filename_len;
01335 
01336        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
01337               return;
01338        }
01339 
01340        /* Prevent read_mib() from printing any errors. */
01341        snmp_disable_stderrlog();
01342        
01343        if (!read_mib(filename)) {
01344               char *error = strerror(errno);
01345               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading MIB file '%s': %s", filename, error);
01346               RETURN_FALSE;
01347        }
01348        RETURN_TRUE;
01349 }
01350 /* }}} */
01351 
01352 #endif
01353 
01354 /*
01355  * Local variables:
01356  * tab-width: 4
01357  * c-basic-offset: 4
01358  * End:
01359  * vim600: sw=4 ts=4 fdm=marker
01360  * vim<600: sw=4 ts=4
01361  */