/src/net-snmp/agent/snmp_vars.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * snmp_vars.c - return a pointer to the named variable. |
3 | | */ |
4 | | /** |
5 | | * @addtogroup library |
6 | | * |
7 | | * @{ |
8 | | */ |
9 | | /* Portions of this file are subject to the following copyright(s). See |
10 | | * the Net-SNMP's COPYING file for more details and other copyrights |
11 | | * that may apply: |
12 | | */ |
13 | | /* Portions of this file are subject to the following copyright(s). See |
14 | | * the Net-SNMP's COPYING file for more details and other copyrights |
15 | | * that may apply: |
16 | | */ |
17 | | /*********************************************************** |
18 | | Copyright 1988, 1989, 1990 by Carnegie Mellon University |
19 | | Copyright 1989 TGV, Incorporated |
20 | | |
21 | | All Rights Reserved |
22 | | |
23 | | Permission to use, copy, modify, and distribute this software and its |
24 | | documentation for any purpose and without fee is hereby granted, |
25 | | provided that the above copyright notice appear in all copies and that |
26 | | both that copyright notice and this permission notice appear in |
27 | | supporting documentation, and that the name of CMU and TGV not be used |
28 | | in advertising or publicity pertaining to distribution of the software |
29 | | without specific, written prior permission. |
30 | | |
31 | | CMU AND TGV DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
32 | | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
33 | | EVENT SHALL CMU OR TGV BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
34 | | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF |
35 | | USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR |
36 | | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
37 | | PERFORMANCE OF THIS SOFTWARE. |
38 | | ******************************************************************/ |
39 | | /* |
40 | | * Portions of this file are copyrighted by: |
41 | | * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. |
42 | | * Use is subject to license terms specified in the COPYING file |
43 | | * distributed with the Net-SNMP package. |
44 | | * |
45 | | * Portions of this file are copyrighted by: |
46 | | * Copyright (c) 2016 VMware, Inc. All rights reserved. |
47 | | * Use is subject to license terms specified in the COPYING file |
48 | | * distributed with the Net-SNMP package. |
49 | | */ |
50 | | |
51 | | /* |
52 | | * additions, fixes and enhancements for Linux by Erik Schoenfelder |
53 | | * (schoenfr@ibr.cs.tu-bs.de) 1994/1995. |
54 | | * Linux additions taken from CMU to UCD stack by Jennifer Bray of Origin |
55 | | * (jbray@origin-at.co.uk) 1997 |
56 | | */ |
57 | | |
58 | | /* |
59 | | * XXXWWW merge todo: incl/excl range changes in differences between |
60 | | * 1.194 and 1.199 |
61 | | */ |
62 | | |
63 | | #include <net-snmp/net-snmp-config.h> |
64 | | #ifdef HAVE_SYS_PARAM_H |
65 | | #include <sys/param.h> |
66 | | #endif |
67 | | #ifdef HAVE_STRING_H |
68 | | #include <string.h> |
69 | | #endif |
70 | | #ifdef HAVE_STDLIB_H |
71 | | #include <stdlib.h> |
72 | | #endif |
73 | | #include <sys/types.h> |
74 | | #include <stdio.h> |
75 | | #include <fcntl.h> |
76 | | #include <errno.h> |
77 | | |
78 | | #ifdef TIME_WITH_SYS_TIME |
79 | | # include <sys/time.h> |
80 | | # include <time.h> |
81 | | #else |
82 | | # ifdef HAVE_SYS_TIME_H |
83 | | # include <sys/time.h> |
84 | | # else |
85 | | # include <time.h> |
86 | | # endif |
87 | | #endif |
88 | | #ifdef HAVE_SYS_SOCKET_H |
89 | | # include <sys/socket.h> |
90 | | #endif |
91 | | #ifdef HAVE_SYS_STREAM_H |
92 | | # ifdef sysv5UnixWare7 |
93 | | # define _KMEMUSER 1 /* <sys/stream.h> needs this for queue_t */ |
94 | | # endif |
95 | | #include <sys/stream.h> |
96 | | #endif |
97 | | #ifdef HAVE_SYS_SOCKETVAR_H |
98 | | # include <sys/socketvar.h> |
99 | | #endif |
100 | | #ifdef HAVE_NETINET_IN_H |
101 | | #include <netinet/in.h> |
102 | | #endif |
103 | | #ifdef HAVE_NETINET_IN_SYSTM_H |
104 | | #include <netinet/in_systm.h> |
105 | | #endif |
106 | | #ifdef HAVE_NETINET_IP_H |
107 | | #include <netinet/ip.h> |
108 | | #endif |
109 | | #ifdef NETSNMP_ENABLE_IPV6 |
110 | | #ifdef HAVE_NETINET_IP6_H |
111 | | #include <netinet/ip6.h> |
112 | | #endif |
113 | | #endif |
114 | | #ifdef HAVE_SYS_QUEUE_H |
115 | | #include <sys/queue.h> |
116 | | #endif |
117 | | #ifdef HAVE_NET_ROUTE_H |
118 | | #include <net/route.h> |
119 | | #endif |
120 | | #ifdef HAVE_NETINET_IP_VAR_H |
121 | | #include <netinet/ip_var.h> |
122 | | #endif |
123 | | #ifdef NETSNMP_ENABLE_IPV6 |
124 | | #ifdef HAVE_NETNETSNMP_ENABLE_IPV6_IP6_VAR_H |
125 | | #include <netinet6/ip6_var.h> |
126 | | #endif |
127 | | #endif |
128 | | #ifdef HAVE_NETINET_IN_PCB_H |
129 | | #include <netinet/in_pcb.h> |
130 | | #endif |
131 | | #ifdef HAVE_INET_MIB2_H |
132 | | #include <inet/mib2.h> |
133 | | #endif |
134 | | |
135 | | #include <net-snmp/net-snmp-includes.h> |
136 | | #include <net-snmp/agent/net-snmp-agent-includes.h> |
137 | | #include <net-snmp/agent/mib_modules.h> |
138 | | #include <net-snmp/agent/agent_sysORTable.h> |
139 | | #include "agent_global_vars.h" |
140 | | #include "kernel.h" |
141 | | |
142 | | #include "mibgroup/struct.h" |
143 | | #include "snmpd.h" |
144 | | #include "agentx/agentx_config.h" |
145 | | #include "agentx/subagent.h" |
146 | | #include "net-snmp/agent/all_helpers.h" |
147 | | #include "agent_module_includes.h" |
148 | | #include "net-snmp/library/container.h" |
149 | | |
150 | | #if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) |
151 | | #include <openssl/ssl.h> |
152 | | #include <openssl/x509v3.h> |
153 | | #include <net-snmp/library/cert_util.h> |
154 | | #endif |
155 | | |
156 | | #include "snmp_perl.h" |
157 | | |
158 | | #ifndef MIN |
159 | | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) |
160 | | #endif |
161 | | |
162 | | static char done_init_agent = 0; |
163 | | |
164 | | struct module_init_list *initlist = NULL; |
165 | | struct module_init_list *noinitlist = NULL; |
166 | | |
167 | | /* |
168 | | * Each variable name is placed in the variable table, without the |
169 | | * terminating substring that determines the instance of the variable. When |
170 | | * a string is found that is lexicographicly preceded by the input string, |
171 | | * the function for that entry is called to find the method of access of the |
172 | | * instance of the named variable. If that variable is not found, NULL is |
173 | | * returned, and the search through the table continues (it will probably |
174 | | * stop at the next entry). If it is found, the function returns a character |
175 | | * pointer and a length or a function pointer. The former is the address |
176 | | * of the operand, the latter is a write routine for the variable. |
177 | | * |
178 | | * u_char * |
179 | | * findVar(name, length, exact, var_len, write_method) |
180 | | * oid *name; IN/OUT - input name requested, output name found |
181 | | * int length; IN/OUT - number of sub-ids in the in and out oid's |
182 | | * int exact; IN - TRUE if an exact match was requested. |
183 | | * int len; OUT - length of variable or 0 if function returned. |
184 | | * int write_method; OUT - pointer to function to set variable, |
185 | | * otherwise 0 |
186 | | * |
187 | | * The writeVar function is returned to handle row addition or complex |
188 | | * writes that require boundary checking or executing an action. |
189 | | * This routine will be called three times for each varbind in the packet. |
190 | | * The first time for each varbind, action is set to RESERVE1. The type |
191 | | * and value should be checked during this pass. If any other variables |
192 | | * in the MIB depend on this variable, this variable will be stored away |
193 | | * (but *not* committed!) in a place where it can be found by a call to |
194 | | * writeVar for a dependent variable, even in the same PDU. During |
195 | | * the second pass, action is set to RESERVE2. If this variable is dependent |
196 | | * on any other variables, it will check them now. It must check to see |
197 | | * if any non-committed values have been stored for variables in the same |
198 | | * PDU that it depends on. Sometimes resources will need to be reserved |
199 | | * in the first two passes to guarantee that the operation can proceed |
200 | | * during the third pass. During the third pass, if there were no errors |
201 | | * in the first two passes, writeVar is called for every varbind with action |
202 | | * set to COMMIT. It is now that the values should be written. If there |
203 | | * were errors during the first two passes, writeVar is called in the third |
204 | | * pass once for each varbind, with the action set to FREE. An opportunity |
205 | | * is thus provided to free those resources reserved in the first two passes. |
206 | | * |
207 | | * writeVar(action, var_val, var_val_type, var_val_len, statP, name, name_len) |
208 | | * int action; IN - RESERVE1, RESERVE2, COMMIT, or FREE |
209 | | * u_char *var_val; IN - input or output buffer space |
210 | | * u_char var_val_type; IN - type of input buffer |
211 | | * int var_val_len; IN - input and output buffer len |
212 | | * u_char *statP; IN - pointer to local statistic |
213 | | * oid *name IN - pointer to name requested |
214 | | * int name_len IN - number of sub-ids in the name |
215 | | */ |
216 | | |
217 | | long long_return; |
218 | | #ifndef ibm032 |
219 | | u_char return_buf[258]; |
220 | | #else |
221 | | u_char return_buf[256]; /* nee 64 */ |
222 | | #endif |
223 | | |
224 | | static int |
225 | | _warn_if_all_disabled(int maj, int min, void *serverarg, void *clientarg); |
226 | | |
227 | | int callback_master_num = -1; |
228 | | |
229 | | #ifdef NETSNMP_TRANSPORT_CALLBACK_DOMAIN |
230 | | netsnmp_session *callback_master_sess = NULL; |
231 | | |
232 | | static void |
233 | | _init_agent_callback_transport(void) |
234 | 2.62k | { |
235 | | /* |
236 | | * always register a callback transport for internal use |
237 | | */ |
238 | 2.62k | callback_master_sess = netsnmp_callback_open(0, handle_snmp_packet, |
239 | 2.62k | netsnmp_agent_check_packet, |
240 | 2.62k | netsnmp_agent_check_parse); |
241 | 2.62k | if (callback_master_sess) |
242 | 2.62k | callback_master_num = callback_master_sess->local_port; |
243 | 2.62k | } |
244 | | #else |
245 | | #define _init_agent_callback_transport() |
246 | | #endif |
247 | | |
248 | | /** |
249 | | * Initialize the agent. Calls into init_agent_read_config to set that app's |
250 | | * configuration file in the appropriate default storage space, |
251 | | * NETSNMP_DS_LIB_APPTYPE. Need to call init_agent before calling init_snmp. |
252 | | * |
253 | | * @param app the configuration file to be read in, gets stored in default |
254 | | * storage |
255 | | * |
256 | | * @return Returns non-zero on failure and zero on success. |
257 | | * |
258 | | * @see init_snmp |
259 | | */ |
260 | | int |
261 | | init_agent(const char *app) |
262 | 2.62k | { |
263 | 2.62k | int r = 0; |
264 | | |
265 | 2.62k | if(++done_init_agent > 1) { |
266 | 0 | snmp_log(LOG_WARNING, "ignoring extra call to init_agent (%d)\n", |
267 | 0 | done_init_agent); |
268 | 0 | return r; |
269 | 0 | } |
270 | | |
271 | | /* |
272 | | * get current time (ie, the time the agent started) |
273 | | */ |
274 | 2.62k | netsnmp_set_agent_starttime(NULL); |
275 | | |
276 | | /* |
277 | | * we handle alarm signals ourselves in the select loop |
278 | | */ |
279 | 2.62k | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
280 | 2.62k | NETSNMP_DS_LIB_ALARM_DONT_USE_SIG, 1); |
281 | | |
282 | 2.62k | r = init_kmem("/dev/kmem") ? 0 : -EACCES; |
283 | | |
284 | 2.62k | setup_tree(); |
285 | | |
286 | 2.62k | init_agent_read_config(app); |
287 | | |
288 | | #ifdef TESTING |
289 | | auto_nlist_print_tree(-2, 0); |
290 | | #endif |
291 | | |
292 | 2.62k | _init_agent_callback_transport(); |
293 | | |
294 | 2.62k | #ifndef NETSNMP_FEATURE_REMOVE_RUNTIME_DISABLE_VERSION |
295 | 2.62k | snmp_register_callback(SNMP_CALLBACK_LIBRARY, |
296 | 2.62k | SNMP_CALLBACK_POST_READ_CONFIG, |
297 | 2.62k | _warn_if_all_disabled, NULL); |
298 | 2.62k | #endif /* NETSNMP_FEATURE_REMOVE_RUNTIME_DISABLE_VERSION */ |
299 | | |
300 | 2.62k | netsnmp_init_helpers(); |
301 | 2.62k | init_traps(); |
302 | 2.62k | netsnmp_container_init_list(); |
303 | 2.62k | init_agent_sysORTable(); |
304 | | |
305 | 2.62k | #if defined(USING_AGENTX_SUBAGENT_MODULE) || defined(USING_AGENTX_MASTER_MODULE) |
306 | | /* |
307 | | * initialize agentx configs |
308 | | */ |
309 | 2.62k | agentx_config_init(); |
310 | 2.62k | #if defined(USING_AGENTX_SUBAGENT_MODULE) |
311 | 2.62k | if(netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, |
312 | 2.62k | NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) |
313 | 0 | subagent_init(); |
314 | 2.62k | #endif |
315 | 2.62k | #endif |
316 | | |
317 | | /* |
318 | | * Register configuration tokens from transport modules. |
319 | | */ |
320 | 2.62k | #ifdef NETSNMP_TRANSPORT_UDP_DOMAIN |
321 | 2.62k | netsnmp_udp_agent_config_tokens_register(); |
322 | 2.62k | #endif |
323 | 2.62k | #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN |
324 | 2.62k | netsnmp_udp6_agent_config_tokens_register(); |
325 | 2.62k | #endif |
326 | 2.62k | #ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN |
327 | 2.62k | netsnmp_unix_agent_config_tokens_register(); |
328 | 2.62k | #endif |
329 | | |
330 | | #ifdef NETSNMP_EMBEDDED_PERL |
331 | | init_perl(); |
332 | | #endif |
333 | | |
334 | 2.62k | #if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) && NETSNMP_TRANSPORT_TLSBASE_DOMAIN |
335 | | /** init secname mapping */ |
336 | 2.62k | netsnmp_certs_agent_init(); |
337 | 2.62k | #endif |
338 | | |
339 | 2.62k | #ifdef USING_AGENTX_SUBAGENT_MODULE |
340 | | /* |
341 | | * don't init agent modules for a sub-agent |
342 | | */ |
343 | 2.62k | if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, |
344 | 2.62k | NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) |
345 | 0 | return r; |
346 | 2.62k | #endif |
347 | | |
348 | 2.62k | # include "agent_module_inits.h" |
349 | | |
350 | 2.62k | return r; |
351 | 2.62k | } /* end init_agent() */ |
352 | | |
353 | | const oid nullOid[] = { 0, 0 }; |
354 | | const int nullOidLen = sizeof(nullOid); |
355 | | |
356 | | void |
357 | | shutdown_agent(void) |
358 | 2.62k | { |
359 | 2.62k | #if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) && NETSNMP_TRANSPORT_TLSBASE_DOMAIN |
360 | 2.62k | netsnmp_certs_shutdown(); |
361 | 2.62k | #endif |
362 | | /* probably some of this can be called as shutdown callback */ |
363 | 2.62k | shutdown_tree(); |
364 | 2.62k | clear_context(); |
365 | 2.62k | netsnmp_clear_callback_list(); |
366 | 2.62k | netsnmp_clear_tdomain_list(); |
367 | 2.62k | netsnmp_clear_handler_list(); |
368 | 2.62k | shutdown_agent_sysORTable(); |
369 | 2.62k | netsnmp_container_free_list(); |
370 | 2.62k | clear_sec_mod(); |
371 | 2.62k | clear_snmp_enum(); |
372 | 2.62k | clear_callback(); |
373 | 2.62k | shutdown_secmod(); |
374 | 2.62k | netsnmp_addrcache_destroy(); |
375 | 2.62k | free_kmem(); |
376 | | |
377 | 2.62k | done_init_agent = 0; |
378 | 2.62k | } |
379 | | |
380 | | |
381 | | void |
382 | | add_to_init_list(char *module_list) |
383 | 2.62k | { |
384 | 2.62k | struct module_init_list *newitem, **list; |
385 | 2.62k | char *cp; |
386 | 2.62k | char *st; |
387 | | |
388 | 2.62k | if (module_list == NULL) { |
389 | 0 | return; |
390 | 2.62k | } else { |
391 | 2.62k | cp = (char *) module_list; |
392 | 2.62k | } |
393 | | |
394 | 2.62k | if (*cp == '-' || *cp == '!') { |
395 | 2.62k | cp++; |
396 | 2.62k | list = &noinitlist; |
397 | 2.62k | } else { |
398 | 0 | list = &initlist; |
399 | 0 | } |
400 | | |
401 | 2.62k | cp = strtok_r(cp, ", :", &st); |
402 | 5.25k | while (cp) { |
403 | 2.62k | newitem = calloc(1, sizeof(*initlist)); |
404 | 2.62k | newitem->module_name = strdup(cp); |
405 | 2.62k | newitem->next = *list; |
406 | 2.62k | *list = newitem; |
407 | 2.62k | cp = strtok_r(NULL, ", :", &st); |
408 | 2.62k | } |
409 | 2.62k | } |
410 | | |
411 | | int |
412 | | should_init(const char *module_name) |
413 | 13.1k | { |
414 | 13.1k | struct module_init_list *listp; |
415 | | |
416 | | /* |
417 | | * a definitive list takes priority |
418 | | */ |
419 | 13.1k | if (initlist) { |
420 | 0 | listp = initlist; |
421 | 0 | while (listp) { |
422 | 0 | if (strcmp(listp->module_name, module_name) == 0) { |
423 | 0 | DEBUGMSGTL(("mib_init", "initializing: %s\n", |
424 | 0 | module_name)); |
425 | 0 | return DO_INITIALIZE; |
426 | 0 | } |
427 | 0 | listp = listp->next; |
428 | 0 | } |
429 | 0 | DEBUGMSGTL(("mib_init", "skipping: %s\n", module_name)); |
430 | 0 | return DONT_INITIALIZE; |
431 | 0 | } |
432 | | |
433 | | /* |
434 | | * initialize it only if not on the bad list (bad module, no bone) |
435 | | */ |
436 | 13.1k | if (noinitlist) { |
437 | 13.1k | listp = noinitlist; |
438 | 10.3M | while (listp) { |
439 | 10.3M | if (strcmp(listp->module_name, module_name) == 0) { |
440 | 5.25k | DEBUGMSGTL(("mib_init", "skipping: %s\n", |
441 | 5.25k | module_name)); |
442 | 5.25k | return DONT_INITIALIZE; |
443 | 5.25k | } |
444 | 10.3M | listp = listp->next; |
445 | 10.3M | } |
446 | 13.1k | } |
447 | 7.87k | DEBUGMSGTL(("mib_init", "initializing: %s\n", module_name)); |
448 | | |
449 | | /* |
450 | | * initialize it |
451 | | */ |
452 | 7.87k | return DO_INITIALIZE; |
453 | 13.1k | } |
454 | | |
455 | | static int |
456 | | _warn_if_all_disabled(int maj, int min, void *serverarg, void *clientarg) |
457 | 2.62k | { |
458 | 2.62k | const char * name = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, |
459 | 2.62k | NETSNMP_DS_LIB_APPTYPE); |
460 | 2.62k | const int agent_mode = netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, |
461 | 2.62k | NETSNMP_DS_AGENT_ROLE); |
462 | 2.62k | int enabled = 0; |
463 | 2.62k | if (NULL==name) |
464 | 0 | name = "snmpd"; |
465 | | |
466 | 2.62k | if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, |
467 | 2.62k | NETSNMP_DS_LIB_DISABLE_V3)) |
468 | 2.62k | ++enabled; |
469 | 2.62k | #ifndef NETSNMP_DISABLE_SNMPV2C |
470 | 2.62k | if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, |
471 | 2.62k | NETSNMP_DS_LIB_DISABLE_V2c)) |
472 | 2.62k | ++enabled; |
473 | 2.62k | #endif /* NETSNMP_DISABLE_SNMPV2C */ |
474 | 2.62k | #ifndef NETSNMP_DISABLE_SNMPV1 |
475 | 2.62k | if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, |
476 | 2.62k | NETSNMP_DS_LIB_DISABLE_V1)) |
477 | 2.62k | ++enabled; |
478 | 2.62k | #endif /* NETSNMP_DISABLE_SNMPV1 */ |
479 | | |
480 | 2.62k | if (0 == enabled) { |
481 | 0 | if ((MASTER_AGENT == agent_mode) && (strcmp(name, "snmptrapd") != 0)) { |
482 | 0 | snmp_log(LOG_WARNING, |
483 | 0 | "Warning: all protocol versions are runtime disabled.\n" |
484 | 0 | " It's unlikely this agent can serve any useful purpose in this state.\n" |
485 | 0 | " Check %s.conf file(s) for this agent.\n", name); |
486 | 0 | } else if (!strcmp(name, "snmptrapd") && |
487 | 0 | !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, |
488 | 0 | NETSNMP_DS_APP_NO_AUTHORIZATION)) { |
489 | 0 | snmp_log(LOG_WARNING, |
490 | 0 | "Warning: all protocol versions are runtime disabled.\n" |
491 | 0 | "This receiver will *NOT* accept any incoming notifications.\n"); |
492 | 0 | } |
493 | 0 | } |
494 | 2.62k | return SNMP_ERR_NOERROR; |
495 | 2.62k | } |
496 | | |
497 | | /** @} */ |
498 | | |