net-snmp 5.7
|
00001 /* 00002 * snmp_vars.c - return a pointer to the named variable. 00003 */ 00009 /* Portions of this file are subject to the following copyright(s). See 00010 * the Net-SNMP's COPYING file for more details and other copyrights 00011 * that may apply: 00012 */ 00013 /* Portions of this file are subject to the following copyright(s). See 00014 * the Net-SNMP's COPYING file for more details and other copyrights 00015 * that may apply: 00016 */ 00017 /*********************************************************** 00018 Copyright 1988, 1989, 1990 by Carnegie Mellon University 00019 Copyright 1989 TGV, Incorporated 00020 00021 All Rights Reserved 00022 00023 Permission to use, copy, modify, and distribute this software and its 00024 documentation for any purpose and without fee is hereby granted, 00025 provided that the above copyright notice appear in all copies and that 00026 both that copyright notice and this permission notice appear in 00027 supporting documentation, and that the name of CMU and TGV not be used 00028 in advertising or publicity pertaining to distribution of the software 00029 without specific, written prior permission. 00030 00031 CMU AND TGV DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 00032 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 00033 EVENT SHALL CMU OR TGV BE LIABLE FOR ANY SPECIAL, INDIRECT OR 00034 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 00035 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 00036 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00037 PERFORMANCE OF THIS SOFTWARE. 00038 ******************************************************************/ 00039 /* 00040 * Portions of this file are copyrighted by: 00041 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. 00042 * Use is subject to license terms specified in the COPYING file 00043 * distributed with the Net-SNMP package. 00044 */ 00045 00046 /* 00047 * additions, fixes and enhancements for Linux by Erik Schoenfelder 00048 * (schoenfr@ibr.cs.tu-bs.de) 1994/1995. 00049 * Linux additions taken from CMU to UCD stack by Jennifer Bray of Origin 00050 * (jbray@origin-at.co.uk) 1997 00051 */ 00052 /* 00053 * Portions of this file are copyrighted by: 00054 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. 00055 * Use is subject to license terms specified in the COPYING file 00056 * distributed with the Net-SNMP package. 00057 */ 00058 00059 /* 00060 * XXXWWW merge todo: incl/excl range changes in differences between 00061 * 1.194 and 1.199 00062 */ 00063 00064 #include <net-snmp/net-snmp-config.h> 00065 #if HAVE_STRING_H 00066 #include <string.h> 00067 #endif 00068 #if HAVE_STDLIB_H 00069 #include <stdlib.h> 00070 #endif 00071 #include <sys/types.h> 00072 #include <stdio.h> 00073 #include <fcntl.h> 00074 00075 #if TIME_WITH_SYS_TIME 00076 # include <sys/time.h> 00077 # include <time.h> 00078 #else 00079 # if HAVE_SYS_TIME_H 00080 # include <sys/time.h> 00081 # else 00082 # include <time.h> 00083 # endif 00084 #endif 00085 #if HAVE_SYS_SOCKET_H 00086 # include <sys/socket.h> 00087 #endif 00088 #if HAVE_SYS_STREAM_H 00089 # ifdef sysv5UnixWare7 00090 # define _KMEMUSER 1 /* <sys/stream.h> needs this for queue_t */ 00091 # endif 00092 #include <sys/stream.h> 00093 #endif 00094 #if HAVE_SYS_SOCKETVAR_H 00095 # include <sys/socketvar.h> 00096 #endif 00097 #if HAVE_NETINET_IN_H 00098 #include <netinet/in.h> 00099 #endif 00100 #if HAVE_NETINET_IN_SYSTM_H 00101 #include <netinet/in_systm.h> 00102 #endif 00103 #if HAVE_NETINET_IP_H 00104 #include <netinet/ip.h> 00105 #endif 00106 #ifdef NETSNMP_ENABLE_IPV6 00107 #if HAVE_NETINET_IP6_H 00108 #include <netinet/ip6.h> 00109 #endif 00110 #endif 00111 #if HAVE_SYS_QUEUE_H 00112 #include <sys/queue.h> 00113 #endif 00114 #if HAVE_NET_ROUTE_H 00115 #include <net/route.h> 00116 #endif 00117 #if HAVE_NETINET_IP_VAR_H 00118 #include <netinet/ip_var.h> 00119 #endif 00120 #ifdef NETSNMP_ENABLE_IPV6 00121 #if HAVE_NETNETSNMP_ENABLE_IPV6_IP6_VAR_H 00122 #include <netinet6/ip6_var.h> 00123 #endif 00124 #endif 00125 #if HAVE_NETINET_IN_PCB_H 00126 #include <netinet/in_pcb.h> 00127 #endif 00128 #if HAVE_INET_MIB2_H 00129 #include <inet/mib2.h> 00130 #endif 00131 00132 #include <net-snmp/net-snmp-includes.h> 00133 #include <net-snmp/agent/net-snmp-agent-includes.h> 00134 #include <net-snmp/agent/mib_modules.h> 00135 #include <net-snmp/agent/agent_sysORTable.h> 00136 #include "kernel.h" 00137 00138 #include "mibgroup/struct.h" 00139 #include "snmpd.h" 00140 #include "agentx/agentx_config.h" 00141 #include "agentx/subagent.h" 00142 #include "net-snmp/agent/all_helpers.h" 00143 #include "agent_module_includes.h" 00144 #include "mib_module_includes.h" 00145 #include "net-snmp/library/container.h" 00146 00147 #if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) 00148 #include <openssl/ssl.h> 00149 #include <openssl/x509v3.h> 00150 #include <net-snmp/library/cert_util.h> 00151 #endif 00152 00153 #include "snmp_perl.h" 00154 00155 #ifndef MIN 00156 #define MIN(a,b) (((a) < (b)) ? (a) : (b)) 00157 #endif 00158 00159 static char done_init_agent = 0; 00160 00161 struct module_init_list *initlist = NULL; 00162 struct module_init_list *noinitlist = NULL; 00163 00164 /* 00165 * mib clients are passed a pointer to a oid buffer. Some mib clients 00166 * * (namely, those first noticed in mibII/vacm.c) modify this oid buffer 00167 * * before they determine if they really need to send results back out 00168 * * using it. If the master agent determined that the client was not the 00169 * * right one to talk with, it will use the same oid buffer to pass to the 00170 * * rest of the clients, which may not longer be valid. This should be 00171 * * fixed in all clients rather than the master. However, its not a 00172 * * particularily easy bug to track down so this saves debugging time at 00173 * * the expense of a few memcpy's. 00174 */ 00175 #define MIB_CLIENTS_ARE_EVIL 1 00176 00177 extern netsnmp_subtree *subtrees; 00178 00179 /* 00180 * Each variable name is placed in the variable table, without the 00181 * terminating substring that determines the instance of the variable. When 00182 * a string is found that is lexicographicly preceded by the input string, 00183 * the function for that entry is called to find the method of access of the 00184 * instance of the named variable. If that variable is not found, NULL is 00185 * returned, and the search through the table continues (it will probably 00186 * stop at the next entry). If it is found, the function returns a character 00187 * pointer and a length or a function pointer. The former is the address 00188 * of the operand, the latter is a write routine for the variable. 00189 * 00190 * u_char * 00191 * findVar(name, length, exact, var_len, write_method) 00192 * oid *name; IN/OUT - input name requested, output name found 00193 * int length; IN/OUT - number of sub-ids in the in and out oid's 00194 * int exact; IN - TRUE if an exact match was requested. 00195 * int len; OUT - length of variable or 0 if function returned. 00196 * int write_method; OUT - pointer to function to set variable, 00197 * otherwise 0 00198 * 00199 * The writeVar function is returned to handle row addition or complex 00200 * writes that require boundary checking or executing an action. 00201 * This routine will be called three times for each varbind in the packet. 00202 * The first time for each varbind, action is set to RESERVE1. The type 00203 * and value should be checked during this pass. If any other variables 00204 * in the MIB depend on this variable, this variable will be stored away 00205 * (but *not* committed!) in a place where it can be found by a call to 00206 * writeVar for a dependent variable, even in the same PDU. During 00207 * the second pass, action is set to RESERVE2. If this variable is dependent 00208 * on any other variables, it will check them now. It must check to see 00209 * if any non-committed values have been stored for variables in the same 00210 * PDU that it depends on. Sometimes resources will need to be reserved 00211 * in the first two passes to guarantee that the operation can proceed 00212 * during the third pass. During the third pass, if there were no errors 00213 * in the first two passes, writeVar is called for every varbind with action 00214 * set to COMMIT. It is now that the values should be written. If there 00215 * were errors during the first two passes, writeVar is called in the third 00216 * pass once for each varbind, with the action set to FREE. An opportunity 00217 * is thus provided to free those resources reserved in the first two passes. 00218 * 00219 * writeVar(action, var_val, var_val_type, var_val_len, statP, name, name_len) 00220 * int action; IN - RESERVE1, RESERVE2, COMMIT, or FREE 00221 * u_char *var_val; IN - input or output buffer space 00222 * u_char var_val_type; IN - type of input buffer 00223 * int var_val_len; IN - input and output buffer len 00224 * u_char *statP; IN - pointer to local statistic 00225 * oid *name IN - pointer to name requested 00226 * int name_len IN - number of sub-ids in the name 00227 */ 00228 00229 long long_return; 00230 #ifndef ibm032 00231 u_char return_buf[258]; 00232 #else 00233 u_char return_buf[256]; /* nee 64 */ 00234 #endif 00235 00236 int callback_master_num = -1; 00237 00238 #ifdef NETSNMP_TRANSPORT_CALLBACK_DOMAIN 00239 netsnmp_session *callback_master_sess = NULL; 00240 00241 static void 00242 _init_agent_callback_transport(void) 00243 { 00244 /* 00245 * always register a callback transport for internal use 00246 */ 00247 callback_master_sess = netsnmp_callback_open(0, handle_snmp_packet, 00248 netsnmp_agent_check_packet, 00249 netsnmp_agent_check_parse); 00250 if (callback_master_sess) 00251 callback_master_num = callback_master_sess->local_port; 00252 } 00253 #else 00254 #define _init_agent_callback_transport() 00255 #endif 00256 00269 int 00270 init_agent(const char *app) 00271 { 00272 int r = 0; 00273 00274 if(++done_init_agent > 1) { 00275 snmp_log(LOG_WARNING, "ignoring extra call to init_agent (%d)\n", 00276 done_init_agent); 00277 return r; 00278 } 00279 00280 /* 00281 * get current time (ie, the time the agent started) 00282 */ 00283 netsnmp_set_agent_starttime(NULL); 00284 00285 /* 00286 * we handle alarm signals ourselves in the select loop 00287 */ 00288 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 00289 NETSNMP_DS_LIB_ALARM_DONT_USE_SIG, 1); 00290 00291 #ifdef NETSNMP_CAN_USE_NLIST 00292 init_kmem("/dev/kmem"); 00293 #endif 00294 00295 setup_tree(); 00296 00297 init_agent_read_config(app); 00298 00299 #ifdef TESTING 00300 auto_nlist_print_tree(-2, 0); 00301 #endif 00302 00303 _init_agent_callback_transport(); 00304 00305 netsnmp_init_helpers(); 00306 init_traps(); 00307 netsnmp_container_init_list(); 00308 init_agent_sysORTable(); 00309 00310 #if defined(USING_AGENTX_SUBAGENT_MODULE) || defined(USING_AGENTX_MASTER_MODULE) 00311 /* 00312 * initialize agentx configs 00313 */ 00314 agentx_config_init(); 00315 #if defined(USING_AGENTX_SUBAGENT_MODULE) 00316 if(netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 00317 NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) 00318 subagent_init(); 00319 #endif 00320 #endif 00321 00322 /* 00323 * Register configuration tokens from transport modules. 00324 */ 00325 #ifdef NETSNMP_TRANSPORT_UDP_DOMAIN 00326 netsnmp_udp_agent_config_tokens_register(); 00327 #endif 00328 #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN 00329 netsnmp_udp6_agent_config_tokens_register(); 00330 #endif 00331 #ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN 00332 netsnmp_unix_agent_config_tokens_register(); 00333 #endif 00334 00335 #ifdef NETSNMP_EMBEDDED_PERL 00336 init_perl(); 00337 #endif 00338 00339 #if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) 00340 00341 netsnmp_certs_agent_init(); 00342 #endif 00343 00344 #ifdef USING_AGENTX_SUBAGENT_MODULE 00345 /* 00346 * don't init agent modules for a sub-agent 00347 */ 00348 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 00349 NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) 00350 return r; 00351 #endif 00352 00353 # include "agent_module_inits.h" 00354 00355 return r; 00356 } /* end init_agent() */ 00357 00358 oid nullOid[] = { 0, 0 }; 00359 int nullOidLen = sizeof(nullOid); 00360 00361 void 00362 shutdown_agent(void) { 00363 00364 /* probably some of this can be called as shutdown callback */ 00365 shutdown_tree(); 00366 clear_context(); 00367 netsnmp_clear_callback_list(); 00368 netsnmp_clear_tdomain_list(); 00369 netsnmp_clear_handler_list(); 00370 shutdown_agent_sysORTable(); 00371 netsnmp_container_free_list(); 00372 clear_sec_mod(); 00373 clear_snmp_enum(); 00374 clear_callback(); 00375 shutdown_secmod(); 00376 netsnmp_addrcache_destroy(); 00377 #ifdef NETSNMP_CAN_USE_NLIST 00378 free_kmem(); 00379 #endif 00380 00381 done_init_agent = 0; 00382 } 00383 00384 00385 void 00386 add_to_init_list(char *module_list) 00387 { 00388 struct module_init_list *newitem, **list; 00389 char *cp; 00390 char *st; 00391 00392 if (module_list == NULL) { 00393 return; 00394 } else { 00395 cp = (char *) module_list; 00396 } 00397 00398 if (*cp == '-' || *cp == '!') { 00399 cp++; 00400 list = &noinitlist; 00401 } else { 00402 list = &initlist; 00403 } 00404 00405 cp = strtok_r(cp, ", :", &st); 00406 while (cp) { 00407 newitem = (struct module_init_list *) calloc(1, sizeof(*initlist)); 00408 newitem->module_name = strdup(cp); 00409 newitem->next = *list; 00410 *list = newitem; 00411 cp = strtok_r(NULL, ", :", &st); 00412 } 00413 } 00414 00415 int 00416 should_init(const char *module_name) 00417 { 00418 struct module_init_list *listp; 00419 00420 /* 00421 * a definitive list takes priority 00422 */ 00423 if (initlist) { 00424 listp = initlist; 00425 while (listp) { 00426 if (strcmp(listp->module_name, module_name) == 0) { 00427 DEBUGMSGTL(("mib_init", "initializing: %s\n", 00428 module_name)); 00429 return DO_INITIALIZE; 00430 } 00431 listp = listp->next; 00432 } 00433 DEBUGMSGTL(("mib_init", "skipping: %s\n", module_name)); 00434 return DONT_INITIALIZE; 00435 } 00436 00437 /* 00438 * initialize it only if not on the bad list (bad module, no bone) 00439 */ 00440 if (noinitlist) { 00441 listp = noinitlist; 00442 while (listp) { 00443 if (strcmp(listp->module_name, module_name) == 0) { 00444 DEBUGMSGTL(("mib_init", "skipping: %s\n", 00445 module_name)); 00446 return DONT_INITIALIZE; 00447 } 00448 listp = listp->next; 00449 } 00450 } 00451 DEBUGMSGTL(("mib_init", "initializing: %s\n", module_name)); 00452 00453 /* 00454 * initialize it 00455 */ 00456 return DO_INITIALIZE; 00457 }