1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 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$ */ 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 109ZEND_DECLARE_MODULE_GLOBALS(snmp) 110static PHP_GINIT_FUNCTION(snmp); 111 112/* constant - can be shared among threads */ 113static oid objid_mib[] = {1, 3, 6, 1, 2, 1}; 114 115/* {{{ arginfo */ 116ZEND_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) 122ZEND_END_ARG_INFO() 123 124ZEND_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) 130ZEND_END_ARG_INFO() 131 132ZEND_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) 138ZEND_END_ARG_INFO() 139 140ZEND_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) 146ZEND_END_ARG_INFO() 147 148ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_get_quick_print, 0, 0, 1) 149 ZEND_ARG_INFO(0, d) 150ZEND_END_ARG_INFO() 151 152ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_quick_print, 0, 0, 1) 153 ZEND_ARG_INFO(0, quick_print) 154ZEND_END_ARG_INFO() 155 156#ifdef HAVE_NET_SNMP 157ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_enum_print, 0, 0, 1) 158 ZEND_ARG_INFO(0, enum_print) 159ZEND_END_ARG_INFO() 160 161ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_oid_output_format, 0, 0, 1) 162 ZEND_ARG_INFO(0, oid_format) 163ZEND_END_ARG_INFO() 164#endif 165 166ZEND_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) 174ZEND_END_ARG_INFO() 175 176ZEND_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) 182ZEND_END_ARG_INFO() 183 184ZEND_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) 190ZEND_END_ARG_INFO() 191 192ZEND_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) 198ZEND_END_ARG_INFO() 199 200ZEND_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) 206ZEND_END_ARG_INFO() 207 208ZEND_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) 216ZEND_END_ARG_INFO() 217 218ZEND_BEGIN_ARG_INFO_EX(arginfo_php_snmpv3, 0, 0, 2) 219 ZEND_ARG_INFO(0, s) 220 ZEND_ARG_INFO(0, st) 221ZEND_END_ARG_INFO() 222 223ZEND_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) 234ZEND_END_ARG_INFO() 235 236ZEND_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) 247ZEND_END_ARG_INFO() 248 249ZEND_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) 260ZEND_END_ARG_INFO() 261 262ZEND_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) 273ZEND_END_ARG_INFO() 274 275ZEND_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) 288ZEND_END_ARG_INFO() 289 290ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_valueretrieval, 0, 0, 1) 291 ZEND_ARG_INFO(0, method) 292ZEND_END_ARG_INFO() 293 294ZEND_BEGIN_ARG_INFO(arginfo_snmp_get_valueretrieval, 0) 295ZEND_END_ARG_INFO() 296 297ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_read_mib, 0, 0, 1) 298 ZEND_ARG_INFO(0, filename) 299ZEND_END_ARG_INFO() 300/* }}} */ 301 302/* {{{ snmp_functions[] 303 */ 304const 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 */ 346zend_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 365ZEND_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 */ 372static PHP_GINIT_FUNCTION(snmp) 373{ 374 snmp_globals->valueretrieval = SNMP_VALUE_LIBRARY; 375} 376/* }}} */ 377 378/* {{{ PHP_MINIT_FUNCTION 379 */ 380PHP_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 */ 417PHP_MSHUTDOWN_FUNCTION(snmp) 418{ 419 snmp_shutdown("snmpapp"); 420 421 return SUCCESS; 422} 423/* }}} */ 424 425/* {{{ PHP_MINFO_FUNCTION 426 */ 427PHP_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 441static 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*/ 545static 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 639retry: 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*/ 776static 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 */ 842PHP_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 */ 850PHP_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 */ 858PHP_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 */ 866PHP_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 */ 874PHP_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 */ 890PHP_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 */ 909PHP_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. */ 923PHP_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 */ 950PHP_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 */ 958static 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 */ 971static 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 */ 991static 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 */ 1010static 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 */ 1061static 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 */ 1093static 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 */ 1122PHP_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 */ 1130PHP_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 */ 1138PHP_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 */ 1146PHP_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 */ 1154PHP_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*/ 1174static 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 */ 1267PHP_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 */ 1275PHP_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 */ 1283PHP_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 */ 1291PHP_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 */ 1299PHP_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 */ 1307PHP_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 */ 1323PHP_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. */ 1331PHP_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 */ 1362