File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / snmp / snmp.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:48:01 2012 UTC (12 years, 5 months ago) by misho
Branches: php, MAIN
CVS tags: v5_3_10, HEAD
php

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

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