1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2013 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Rasmus Lerdorf <rasmus@php.net> |
16 | Mike Jackson <mhjack@tscnet.com> |
17 | Steven Lawrance <slawrance@technologist.com> |
18 | Harrie Hazewinkel <harrie@lisanza.net> |
19 | Johann Hanne <jonny@nurfuerspam.de> |
20 +----------------------------------------------------------------------+
21 */
22
23 /* $Id$ */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "php.h"
30 #include "ext/standard/info.h"
31 #include "php_snmp.h"
32
33 #if HAVE_SNMP
34
35 #include <sys/types.h>
36 #ifdef PHP_WIN32
37 #include <winsock2.h>
38 #include <errno.h>
39 #include <process.h>
40 #include "win32/time.h"
41 #elif defined(NETWARE)
42 #ifdef USE_WINSOCK
43 #include <novsock2.h>
44 #else
45 #include <sys/socket.h>
46 #endif
47 #include <errno.h>
48 #include <sys/timeval.h>
49 #else
50 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
53 #ifndef _OSD_POSIX
54 #include <sys/errno.h>
55 #else
56 #include <errno.h> /* BS2000/OSD uses <errno.h>, not <sys/errno.h> */
57 #endif
58 #include <netdb.h>
59 #endif
60 #ifdef HAVE_UNISTD_H
61 #include <unistd.h>
62 #endif
63
64 #ifndef __P
65 #ifdef __GNUC__
66 #define __P(args) args
67 #else
68 #define __P(args) ()
69 #endif
70 #endif
71
72 #ifdef HAVE_NET_SNMP
73 #include <net-snmp/net-snmp-config.h>
74 #include <net-snmp/net-snmp-includes.h>
75 #else
76 #ifdef HAVE_DEFAULT_STORE_H
77 #include "default_store.h"
78 #endif
79 #include "asn1.h"
80 #include "snmp_api.h"
81 #include "snmp_client.h"
82 #include "snmp_impl.h"
83 #include "snmp.h"
84 #include "snmpv3.h"
85 #include "keytools.h"
86 #include "parse.h"
87 #include "mib.h"
88 #ifndef PHP_WIN32
89 /* this doesn't appear to be needed under win32 (perhaps at all)
90 * and the header file is not present in my UCD-SNMP headers */
91 # include "version.h"
92 #endif
93 #include "transform_oids.h"
94 #endif
95 /* Ugly macro, since the length of OIDs in UCD-SNMP and NET-SNMP
96 * is different and this way the code is not full of 'ifdef's.
97 */
98 #define OIDSIZE(p) (sizeof(p)/sizeof(oid))
99
100 /* For really old ucd-snmp versions.. */
101 #ifndef HAVE_SNMP_PARSE_OID
102 #define snmp_parse_oid read_objid
103 #endif
104
105 #define SNMP_VALUE_LIBRARY 0
106 #define SNMP_VALUE_PLAIN 1
107 #define SNMP_VALUE_OBJECT 2
108
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 */
PHP_GINIT_FUNCTION(snmp)372 static PHP_GINIT_FUNCTION(snmp)
373 {
374 snmp_globals->valueretrieval = SNMP_VALUE_LIBRARY;
375 }
376 /* }}} */
377
378 /* {{{ PHP_MINIT_FUNCTION
379 */
PHP_MINIT_FUNCTION(snmp)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 */
PHP_MSHUTDOWN_FUNCTION(snmp)417 PHP_MSHUTDOWN_FUNCTION(snmp)
418 {
419 snmp_shutdown("snmpapp");
420
421 return SUCCESS;
422 }
423 /* }}} */
424
425 /* {{{ PHP_MINFO_FUNCTION
426 */
PHP_MINFO_FUNCTION(snmp)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
php_snmp_getvalue(struct variable_list * vars,zval * snmpval TSRMLS_DC)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 */
php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS,int st,struct snmp_session * session,char * objid,char type,char * value)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 */
php_snmp(INTERNAL_FUNCTION_PARAMETERS,int st,int version)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 */
PHP_FUNCTION(snmpget)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 */
PHP_FUNCTION(snmpgetnext)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 */
PHP_FUNCTION(snmpwalk)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 */
PHP_FUNCTION(snmprealwalk)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 */
PHP_FUNCTION(snmp_get_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 */
PHP_FUNCTION(snmp_set_quick_print)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 */
PHP_FUNCTION(snmp_set_enum_print)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. */
PHP_FUNCTION(snmp_set_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 */
PHP_FUNCTION(snmpset)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 */
netsnmp_session_set_sec_name(struct snmp_session * s,char * name)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 */
netsnmp_session_set_sec_level(struct snmp_session * s,char * level TSRMLS_DC)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 */
netsnmp_session_set_auth_protocol(struct snmp_session * s,char * prot TSRMLS_DC)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 */
netsnmp_session_set_sec_protocol(struct snmp_session * s,char * prot TSRMLS_DC)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 */
1362