1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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 289918 2009-10-25 20:17:04Z jani $ */
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 : {NULL,NULL,NULL}
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 17633 : {
374 17633 : snmp_globals->valueretrieval = SNMP_VALUE_LIBRARY;
375 17633 : }
376 : /* }}} */
377 :
378 : /* {{{ PHP_MINIT_FUNCTION
379 : */
380 : PHP_MINIT_FUNCTION(snmp)
381 17633 : {
382 17633 : init_snmp("snmpapp");
383 :
384 : #ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
385 : /* Prevent update of the snmpapp.conf file */
386 17633 : netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
387 : #endif
388 :
389 : #ifdef HAVE_NET_SNMP
390 17633 : REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_FULL", NETSNMP_OID_OUTPUT_FULL, CONST_CS | CONST_PERSISTENT);
391 17633 : REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NUMERIC", NETSNMP_OID_OUTPUT_NUMERIC, CONST_CS | CONST_PERSISTENT);
392 : #endif
393 :
394 17633 : REGISTER_LONG_CONSTANT("SNMP_VALUE_LIBRARY", SNMP_VALUE_LIBRARY, CONST_CS | CONST_PERSISTENT);
395 17633 : REGISTER_LONG_CONSTANT("SNMP_VALUE_PLAIN", SNMP_VALUE_PLAIN, CONST_CS | CONST_PERSISTENT);
396 17633 : REGISTER_LONG_CONSTANT("SNMP_VALUE_OBJECT", SNMP_VALUE_OBJECT, CONST_CS | CONST_PERSISTENT);
397 :
398 17633 : REGISTER_LONG_CONSTANT("SNMP_BIT_STR", ASN_BIT_STR, CONST_CS | CONST_PERSISTENT);
399 17633 : REGISTER_LONG_CONSTANT("SNMP_OCTET_STR", ASN_OCTET_STR, CONST_CS | CONST_PERSISTENT);
400 17633 : REGISTER_LONG_CONSTANT("SNMP_OPAQUE", ASN_OPAQUE, CONST_CS | CONST_PERSISTENT);
401 17633 : REGISTER_LONG_CONSTANT("SNMP_NULL", ASN_NULL, CONST_CS | CONST_PERSISTENT);
402 17633 : REGISTER_LONG_CONSTANT("SNMP_OBJECT_ID", ASN_OBJECT_ID, CONST_CS | CONST_PERSISTENT);
403 17633 : REGISTER_LONG_CONSTANT("SNMP_IPADDRESS", ASN_IPADDRESS, CONST_CS | CONST_PERSISTENT);
404 17633 : REGISTER_LONG_CONSTANT("SNMP_COUNTER", ASN_GAUGE, CONST_CS | CONST_PERSISTENT);
405 17633 : REGISTER_LONG_CONSTANT("SNMP_UNSIGNED", ASN_UNSIGNED, CONST_CS | CONST_PERSISTENT);
406 17633 : REGISTER_LONG_CONSTANT("SNMP_TIMETICKS", ASN_TIMETICKS, CONST_CS | CONST_PERSISTENT);
407 17633 : REGISTER_LONG_CONSTANT("SNMP_UINTEGER", ASN_UINTEGER, CONST_CS | CONST_PERSISTENT);
408 17633 : REGISTER_LONG_CONSTANT("SNMP_INTEGER", ASN_INTEGER, CONST_CS | CONST_PERSISTENT);
409 17633 : REGISTER_LONG_CONSTANT("SNMP_COUNTER64", ASN_COUNTER64, CONST_CS | CONST_PERSISTENT);
410 :
411 17633 : return SUCCESS;
412 : }
413 : /* }}} */
414 :
415 : /* {{{ PHP_MSHUTDOWN_FUNCTION
416 : */
417 : PHP_MSHUTDOWN_FUNCTION(snmp)
418 17665 : {
419 17665 : snmp_shutdown("snmpapp");
420 :
421 17665 : return SUCCESS;
422 : }
423 : /* }}} */
424 :
425 : /* {{{ PHP_MINFO_FUNCTION
426 : */
427 : PHP_MINFO_FUNCTION(snmp)
428 42 : {
429 42 : php_info_print_table_start();
430 : #ifdef HAVE_NET_SNMP
431 42 : php_info_print_table_row(2, "NET-SNMP Support", "enabled");
432 42 : 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 42 : php_info_print_table_end();
438 42 : }
439 : /* }}} */
440 :
441 : static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_DC)
442 0 : {
443 : zval *val;
444 : #if I64CHARSZ > 2047
445 : char buf[I64CHARSZ + 1];
446 : #else
447 : char buf[2048];
448 : #endif
449 :
450 0 : buf[0] = 0;
451 :
452 0 : if (SNMP_G(valueretrieval) == SNMP_VALUE_LIBRARY) {
453 : #ifdef HAVE_NET_SNMP
454 0 : 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 0 : ZVAL_STRING(snmpval, buf, 1);
459 0 : return;
460 : }
461 :
462 0 : MAKE_STD_ZVAL(val);
463 :
464 0 : switch (vars->type) {
465 : case ASN_BIT_STR: /* 0x03, asn1.h */
466 0 : ZVAL_STRINGL(val, vars->val.bitstring, vars->val_len, 1);
467 0 : break;
468 :
469 : case ASN_OCTET_STR: /* 0x04, asn1.h */
470 : case ASN_OPAQUE: /* 0x44, snmp_impl.h */
471 0 : ZVAL_STRINGL(val, vars->val.string, vars->val_len, 1);
472 0 : break;
473 :
474 : case ASN_NULL: /* 0x05, asn1.h */
475 0 : ZVAL_NULL(val);
476 0 : break;
477 :
478 : case ASN_OBJECT_ID: /* 0x06, asn1.h */
479 : #ifdef HAVE_NET_SNMP
480 0 : 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 0 : ZVAL_STRING(val, buf, 1);
486 0 : break;
487 :
488 : case ASN_IPADDRESS: /* 0x40, snmp_impl.h */
489 0 : 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 0 : buf[sizeof(buf)-1]=0;
493 0 : ZVAL_STRING(val, buf, 1);
494 0 : 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 0 : snprintf(buf, sizeof(buf)-1, "%lu", *vars->val.integer);
502 0 : buf[sizeof(buf)-1]=0;
503 0 : ZVAL_STRING(val, buf, 1);
504 0 : break;
505 :
506 : case ASN_INTEGER: /* 0x02, asn1.h */
507 0 : snprintf(buf, sizeof(buf)-1, "%ld", *vars->val.integer);
508 0 : buf[sizeof(buf)-1]=0;
509 0 : ZVAL_STRING(val, buf, 1);
510 0 : break;
511 :
512 : case ASN_COUNTER64: /* 0x46, snmp_impl.h */
513 0 : printU64(buf, vars->val.counter64);
514 0 : ZVAL_STRING(val, buf, 1);
515 0 : break;
516 :
517 : default:
518 0 : ZVAL_STRING(val, "Unknown value type", 1);
519 : break;
520 : }
521 :
522 0 : if (SNMP_G(valueretrieval) == SNMP_VALUE_PLAIN) {
523 0 : *snmpval = *val;
524 0 : zval_copy_ctor(snmpval);
525 : } else {
526 0 : object_init(snmpval);
527 0 : add_property_long(snmpval, "type", vars->type);
528 0 : 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 0 : {
551 : struct snmp_session *ss;
552 0 : 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 0 : size_t rootlen = 0;
558 0 : int gotroot = 0;
559 : int status, count;
560 : char buf[2048];
561 : char buf2[2048];
562 0 : int keepwalking=1;
563 : char *err;
564 0 : zval *snmpval = NULL;
565 :
566 0 : if (st >= SNMP_CMD_WALK) { /* walk */
567 0 : rootlen = MAX_NAME_LEN;
568 0 : if (strlen(objid)) { /* on a walk, an empty string means top of tree - no error */
569 0 : if (snmp_parse_oid(objid, root, &rootlen)) {
570 0 : gotroot = 1;
571 : } else {
572 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid);
573 : }
574 : }
575 :
576 0 : if (!gotroot) {
577 0 : memmove((char *) root, (char *) objid_mib, sizeof(objid_mib));
578 0 : rootlen = sizeof(objid_mib) / sizeof(oid);
579 0 : gotroot = 1;
580 : }
581 : }
582 :
583 0 : if ((ss = snmp_open(session)) == NULL) {
584 0 : snmp_error(session, NULL, NULL, &err);
585 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open snmp connection: %s", err);
586 0 : free(err);
587 0 : RETURN_FALSE;
588 : }
589 :
590 0 : if (st >= SNMP_CMD_WALK) {
591 0 : memmove((char *)name, (char *)root, rootlen * sizeof(oid));
592 0 : name_length = rootlen;
593 0 : switch(st) {
594 : case SNMP_CMD_WALK:
595 : case SNMP_CMD_REALWALK:
596 0 : array_init(return_value);
597 0 : break;
598 : default:
599 0 : RETVAL_TRUE;
600 : break;
601 : }
602 : }
603 :
604 0 : while (keepwalking) {
605 0 : keepwalking = 0;
606 0 : if ((st == SNMP_CMD_GET) || (st == SNMP_CMD_GETNEXT)) {
607 0 : name_length = MAX_OID_LEN;
608 0 : if (!snmp_parse_oid(objid, name, &name_length)) {
609 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid);
610 0 : snmp_close(ss);
611 0 : RETURN_FALSE;
612 : }
613 0 : pdu = snmp_pdu_create((st == SNMP_CMD_GET) ? SNMP_MSG_GET : SNMP_MSG_GETNEXT);
614 0 : snmp_add_null_var(pdu, name, name_length);
615 0 : } else if (st == SNMP_CMD_SET) {
616 0 : pdu = snmp_pdu_create(SNMP_MSG_SET);
617 0 : if (snmp_add_var(pdu, name, name_length, type, value)) {
618 : #ifdef HAVE_NET_SNMP
619 0 : snprint_objid(buf, sizeof(buf), name, name_length);
620 : #else
621 : sprint_objid(buf, name, name_length);
622 : #endif
623 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not add variable: %s %c %s", buf, type, value);
624 0 : snmp_free_pdu(pdu);
625 0 : snmp_close(ss);
626 0 : RETURN_FALSE;
627 : }
628 0 : } else if (st >= SNMP_CMD_WALK) {
629 0 : if (session->version == SNMP_VERSION_1) {
630 0 : pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
631 : } else {
632 0 : pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
633 0 : pdu->non_repeaters = 0;
634 0 : pdu->max_repetitions = 20;
635 : }
636 0 : snmp_add_null_var(pdu, name, name_length);
637 : }
638 :
639 0 : retry:
640 0 : status = snmp_synch_response(ss, pdu, &response);
641 0 : if (status == STAT_SUCCESS) {
642 0 : if (response->errstat == SNMP_ERR_NOERROR) {
643 0 : for (vars = response->variables; vars; vars = vars->next_variable) {
644 0 : 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 0 : if (st != SNMP_CMD_SET) {
650 0 : MAKE_STD_ZVAL(snmpval);
651 0 : php_snmp_getvalue(vars, snmpval TSRMLS_CC);
652 : }
653 :
654 0 : if (st == SNMP_CMD_GET) {
655 0 : *return_value = *snmpval;
656 0 : zval_copy_ctor(return_value);
657 0 : zval_ptr_dtor(&snmpval);
658 0 : snmp_free_pdu(response);
659 0 : snmp_close(ss);
660 0 : return;
661 0 : } else if (st == SNMP_CMD_GETNEXT) {
662 0 : *return_value = *snmpval;
663 0 : zval_copy_ctor(return_value);
664 0 : snmp_free_pdu(response);
665 0 : snmp_close(ss);
666 0 : return;
667 0 : } else if (st == SNMP_CMD_WALK) {
668 0 : add_next_index_zval(return_value,snmpval); /* Add to returned array */
669 0 : } else if (st == SNMP_CMD_REALWALK && vars->type != SNMP_ENDOFMIBVIEW && vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) {
670 : #ifdef HAVE_NET_SNMP
671 0 : snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
672 : #else
673 : sprint_objid(buf2, vars->name, vars->name_length);
674 : #endif
675 0 : add_assoc_zval(return_value,buf2,snmpval);
676 : }
677 0 : if (st >= SNMP_CMD_WALK && st != SNMP_CMD_SET) {
678 0 : if (vars->type != SNMP_ENDOFMIBVIEW &&
679 : vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) {
680 0 : if (snmp_oid_compare(name, name_length, vars->name, vars->name_length) >= 0) {
681 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error: OID not increasing: %s",name);
682 0 : keepwalking = 0;
683 : } else {
684 0 : memmove((char *)name, (char *)vars->name,vars->name_length * sizeof(oid));
685 0 : name_length = vars->name_length;
686 0 : keepwalking = 1;
687 : }
688 : }
689 : }
690 : }
691 : } else {
692 0 : if (st != SNMP_CMD_WALK || response->errstat != SNMP_ERR_NOSUCHNAME) {
693 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error in packet: %s", snmp_errstring(response->errstat));
694 0 : if (response->errstat == SNMP_ERR_NOSUCHNAME) {
695 0 : for (count=1, vars = response->variables; vars && count != response->errindex;
696 0 : vars = vars->next_variable, count++);
697 0 : if (vars) {
698 : #ifdef HAVE_NET_SNMP
699 0 : 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 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "This name does not exist: %s",buf);
705 : }
706 0 : if (st == SNMP_CMD_GET) {
707 0 : if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GET)) != NULL) {
708 0 : snmp_free_pdu(response);
709 0 : goto retry;
710 : }
711 0 : } else if (st == SNMP_CMD_SET) {
712 0 : if ((pdu = snmp_fix_pdu(response, SNMP_MSG_SET)) != NULL) {
713 0 : snmp_free_pdu(response);
714 0 : goto retry;
715 : }
716 0 : } else if (st == SNMP_CMD_GETNEXT) {
717 0 : if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) != NULL) {
718 0 : snmp_free_pdu(response);
719 0 : goto retry;
720 : }
721 0 : } else if (st >= SNMP_CMD_WALK) { /* Here we do walks. */
722 0 : if ((pdu = snmp_fix_pdu(response, ((session->version == SNMP_VERSION_1)
723 : ? SNMP_MSG_GETNEXT
724 : : SNMP_MSG_GETBULK))) != NULL) {
725 0 : snmp_free_pdu(response);
726 0 : goto retry;
727 : }
728 : }
729 0 : snmp_free_pdu(response);
730 0 : snmp_close(ss);
731 0 : if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
732 0 : zval_dtor(return_value);
733 : }
734 0 : RETURN_FALSE;
735 : }
736 : }
737 0 : } else if (status == STAT_TIMEOUT) {
738 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "No response from %s", session->peername);
739 0 : if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
740 0 : zval_dtor(return_value);
741 : }
742 0 : snmp_close(ss);
743 0 : RETURN_FALSE;
744 : } else { /* status == STAT_ERROR */
745 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred, quitting");
746 0 : if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
747 0 : zval_dtor(return_value);
748 : }
749 0 : snmp_close(ss);
750 0 : RETURN_FALSE;
751 : }
752 0 : if (response) {
753 0 : snmp_free_pdu(response);
754 : }
755 : } /* keepwalking */
756 0 : 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 0 : {
778 : char *a1, *a2, *a3;
779 : int a1_len, a2_len, a3_len;
780 : struct snmp_session session;
781 0 : long timeout = SNMP_DEFAULT_TIMEOUT;
782 0 : long retries = SNMP_DEFAULT_RETRIES;
783 0 : char type = (char) 0;
784 0 : char *value = (char *) 0, *stype = "";
785 : int value_len, stype_len;
786 : char hostname[MAX_NAME_LEN];
787 0 : int remote_port = 161;
788 : char *pptr;
789 0 : int argc = ZEND_NUM_ARGS();
790 :
791 0 : if (st == SNMP_CMD_SET) {
792 0 : 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 0 : return;
794 : }
795 : } else {
796 : /* SNMP_CMD_GET
797 : * SNMP_CMD_GETNEXT
798 : * SNMP_CMD_WALK
799 : * SNMP_CMD_REALWALK
800 : */
801 0 : if (zend_parse_parameters(argc TSRMLS_CC, "sss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len, &timeout, &retries) == FAILURE) {
802 0 : return;
803 : }
804 : }
805 :
806 0 : if (st == SNMP_CMD_SET) {
807 0 : type = stype[0];
808 : }
809 :
810 0 : snmp_sess_init(&session);
811 0 : strlcpy(hostname, a1, sizeof(hostname));
812 0 : if ((pptr = strchr (hostname, ':'))) {
813 0 : remote_port = strtol (pptr + 1, NULL, 0);
814 : }
815 :
816 0 : session.peername = hostname;
817 0 : session.remote_port = remote_port;
818 0 : 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 0 : session.community = (u_char *)a2;
829 : #endif
830 0 : session.community_len = a2_len;
831 0 : session.retries = retries;
832 0 : session.timeout = timeout;
833 :
834 0 : session.authenticator = NULL;
835 :
836 0 : 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 0 : {
844 0 : php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_1);
845 0 : }
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 0 : {
852 0 : php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_1);
853 0 : }
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 0 : {
860 0 : php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_1);
861 0 : }
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 0 : {
868 0 : php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_1);
869 0 : }
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 0 : {
876 0 : if (zend_parse_parameters_none() == FAILURE) {
877 0 : return;
878 : }
879 :
880 : #ifdef HAVE_NET_SNMP
881 0 : 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 0 : {
892 : long a1;
893 :
894 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
895 0 : return;
896 : }
897 :
898 : #ifdef HAVE_NET_SNMP
899 0 : 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 0 : {
911 : long a1;
912 :
913 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
914 0 : return;
915 : }
916 :
917 0 : 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 0 : {
925 : long a1;
926 :
927 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
928 0 : return;
929 : }
930 :
931 0 : switch ((int) a1) {
932 : case 0:
933 : case NETSNMP_OID_OUTPUT_FULL:
934 0 : a1 = NETSNMP_OID_OUTPUT_FULL;
935 0 : break;
936 :
937 : default:
938 : case NETSNMP_OID_OUTPUT_NUMERIC:
939 0 : a1 = NETSNMP_OID_OUTPUT_NUMERIC;
940 : break;
941 : }
942 :
943 0 : 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 0 : {
952 0 : php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_SET, SNMP_VERSION_1);
953 0 : }
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 0 : {
960 0 : if ((s) && (name)) {
961 0 : s->securityName = strdup(name);
962 0 : s->securityNameLen = strlen(s->securityName);
963 0 : return (0);
964 : }
965 0 : 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 0 : {
973 0 : if ((s) && (level)) {
974 0 : if (!strcasecmp(level, "noAuthNoPriv") || !strcasecmp(level, "nanp")) {
975 0 : s->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
976 0 : return (0);
977 0 : } else if (!strcasecmp(level, "authNoPriv") || !strcasecmp(level, "anp")) {
978 0 : s->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
979 0 : return (0);
980 0 : } else if (!strcasecmp(level, "authPriv") || !strcasecmp(level, "ap")) {
981 0 : s->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
982 0 : return (0);
983 : }
984 : }
985 0 : 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 0 : {
993 0 : if ((s) && (prot)) {
994 0 : if (!strcasecmp(prot, "MD5")) {
995 0 : s->securityAuthProto = usmHMACMD5AuthProtocol;
996 0 : s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
997 0 : return (0);
998 0 : } else if (!strcasecmp(prot, "SHA")) {
999 0 : s->securityAuthProto = usmHMACSHA1AuthProtocol;
1000 0 : s->securityAuthProtoLen = OIDSIZE(usmHMACSHA1AuthProtocol);
1001 0 : return (0);
1002 : }
1003 : }
1004 0 : 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 0 : {
1012 0 : if ((s) && (prot)) {
1013 0 : if (!strcasecmp(prot, "DES")) {
1014 0 : s->securityPrivProto = usmDESPrivProtocol;
1015 0 : s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
1016 0 : return (0);
1017 : #ifdef HAVE_AES
1018 0 : } 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 0 : s->securityPrivProto = usmAES128PrivProtocol;
1036 0 : s->securityPrivProtoLen = USM_PRIV_PROTO_AES128_LEN;
1037 0 : 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 0 : 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 0 : {
1063 : /*
1064 : * make master key from pass phrases
1065 : */
1066 0 : if ((s) && (pass) && strlen(pass)) {
1067 0 : s->securityAuthKeyLen = USM_AUTH_KU_LEN;
1068 0 : if (s->securityAuthProto == NULL) {
1069 : /* get .conf set default */
1070 0 : const oid *def = get_default_authtype(&(s->securityAuthProtoLen));
1071 0 : s->securityAuthProto = snmp_duplicate_objid(def, s->securityAuthProtoLen);
1072 : }
1073 0 : if (s->securityAuthProto == NULL) {
1074 : /* assume MD5 */
1075 0 : s->securityAuthProto =
1076 : snmp_duplicate_objid(usmHMACMD5AuthProtocol, OIDSIZE(usmHMACMD5AuthProtocol));
1077 0 : s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
1078 : }
1079 0 : if (generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
1080 : (u_char *) pass, strlen(pass),
1081 : s->securityAuthKey, &(s->securityAuthKeyLen)) != SNMPERR_SUCCESS) {
1082 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for authentication pass phrase");
1083 0 : return (-2);
1084 : }
1085 0 : return (0);
1086 : }
1087 0 : 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 0 : {
1095 0 : if ((s) && (pass) && strlen(pass)) {
1096 0 : s->securityPrivKeyLen = USM_PRIV_KU_LEN;
1097 0 : if (s->securityPrivProto == NULL) {
1098 : /* get .conf set default */
1099 0 : const oid *def = get_default_privtype(&(s->securityPrivProtoLen));
1100 0 : s->securityPrivProto = snmp_duplicate_objid(def, s->securityPrivProtoLen);
1101 : }
1102 0 : if (s->securityPrivProto == NULL) {
1103 : /* assume DES */
1104 0 : s->securityPrivProto = snmp_duplicate_objid(usmDESPrivProtocol,
1105 : OIDSIZE(usmDESPrivProtocol));
1106 0 : s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
1107 : }
1108 0 : if (generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
1109 : pass, strlen(pass),
1110 : s->securityPrivKey, &(s->securityPrivKeyLen)) != SNMPERR_SUCCESS) {
1111 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for privacy pass phrase");
1112 0 : return (-2);
1113 : }
1114 0 : return (0);
1115 : }
1116 0 : 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 0 : {
1124 0 : php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_2c);
1125 0 : }
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 0 : {
1132 0 : php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_2c);
1133 0 : }
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 0 : {
1140 0 : php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_2c);
1141 0 : }
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 0 : {
1148 0 : php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_2c);
1149 0 : }
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 0 : {
1156 0 : php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_SET, SNMP_VERSION_2c);
1157 0 : }
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 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 0 : {
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 0 : long timeout = SNMP_DEFAULT_TIMEOUT;
1180 0 : long retries = SNMP_DEFAULT_RETRIES;
1181 0 : char type = (char) 0;
1182 0 : char *value = (char *) 0, *stype = "";
1183 : int stype_len, value_len;
1184 : char hostname[MAX_NAME_LEN];
1185 0 : int remote_port = 161;
1186 : char *pptr;
1187 0 : int argc = ZEND_NUM_ARGS();
1188 :
1189 0 : if (st == SNMP_CMD_SET) {
1190 0 : 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 0 : return;
1193 : }
1194 : } else {
1195 : /* SNMP_CMD_GET
1196 : * SNMP_CMD_GETNEXT
1197 : * SNMP_CMD_WALK
1198 : * SNMP_CMD_REALWALK
1199 : */
1200 0 : 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 0 : return;
1203 : }
1204 : }
1205 :
1206 0 : snmp_sess_init(&session);
1207 : /* This is all SNMPv3 */
1208 0 : session.version = SNMP_VERSION_3;
1209 :
1210 : /* Reading the hostname and its optional non-default port number */
1211 0 : strlcpy(hostname, a1, sizeof(hostname));
1212 0 : if ((pptr = strchr(hostname, ':'))) {
1213 0 : remote_port = strtol(pptr + 1, NULL, 0);
1214 : }
1215 0 : session.peername = hostname;
1216 0 : session.remote_port = remote_port;
1217 :
1218 : /* Setting the security name. */
1219 0 : if (netsnmp_session_set_sec_name(&session, a2)) {
1220 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could net set security name: %s", a2);
1221 0 : RETURN_FALSE;
1222 : }
1223 :
1224 : /* Setting the security level. */
1225 0 : if (netsnmp_session_set_sec_level(&session, a3 TSRMLS_CC)) {
1226 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security level: %s", a3);
1227 0 : RETURN_FALSE;
1228 : }
1229 :
1230 : /* Setting the authentication protocol. */
1231 0 : if (netsnmp_session_set_auth_protocol(&session, a4 TSRMLS_CC)) {
1232 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid authentication protocol: %s", a4);
1233 0 : RETURN_FALSE;
1234 : }
1235 :
1236 : /* Setting the authentication passphrase. */
1237 0 : if (netsnmp_session_gen_auth_key(&session, a5 TSRMLS_CC)) {
1238 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not generate key for authentication pass phrase: %s", a5);
1239 0 : RETURN_FALSE;
1240 : }
1241 :
1242 : /* Setting the security protocol. */
1243 0 : if (netsnmp_session_set_sec_protocol(&session, a6 TSRMLS_CC) && a6_len) {
1244 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security protocol: %s", a6);
1245 0 : RETURN_FALSE;
1246 : }
1247 :
1248 : /* Setting the security protocol passphrase. */
1249 0 : if (netsnmp_session_gen_sec_key(&session, a7 TSRMLS_CC) && a7_len) {
1250 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not generate key for security pass phrase: %s", a7);
1251 0 : RETURN_FALSE;
1252 : }
1253 :
1254 0 : if (st == SNMP_CMD_SET) {
1255 0 : type = stype[0];
1256 : }
1257 :
1258 0 : session.retries = retries;
1259 0 : session.timeout = timeout;
1260 :
1261 0 : 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 0 : {
1269 0 : php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET);
1270 0 : }
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 0 : {
1277 0 : php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT);
1278 0 : }
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 0 : {
1285 0 : php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK);
1286 0 : }
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 0 : {
1293 0 : php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_REALWALK);
1294 0 : }
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 0 : {
1301 0 : php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET);
1302 0 : }
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 0 : {
1309 : long method;
1310 :
1311 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
1312 0 : return;
1313 : }
1314 :
1315 0 : if ((method == SNMP_VALUE_LIBRARY) || (method == SNMP_VALUE_PLAIN) || (method == SNMP_VALUE_OBJECT)) {
1316 0 : 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 0 : {
1325 0 : 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 0 : {
1333 : char *filename;
1334 : int filename_len;
1335 :
1336 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
1337 0 : return;
1338 : }
1339 :
1340 : /* Prevent read_mib() from printing any errors. */
1341 0 : snmp_disable_stderrlog();
1342 :
1343 0 : if (!read_mib(filename)) {
1344 0 : char *error = strerror(errno);
1345 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading MIB file '%s': %s", filename, error);
1346 0 : RETURN_FALSE;
1347 : }
1348 0 : 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 : */
|