00001 #include <net-snmp/net-snmp-config.h>
00002
00003 #ifdef CAN_USE_NLIST
00004 #if HAVE_STRING_H
00005 #include <string.h>
00006 #else
00007 #include <strings.h>
00008 #endif
00009
00010 #if HAVE_STDLIB_H
00011 #include <stdlib.h>
00012 #endif
00013 #include <stdio.h>
00014 #include <errno.h>
00015 #include <fcntl.h>
00016 #include <netinet/in.h>
00017 #ifdef HAVE_NLIST_H
00018 #include <nlist.h>
00019 #endif
00020 #if HAVE_KVM_H
00021 #include <kvm.h>
00022 #endif
00023
00024 #include <net-snmp/agent/auto_nlist.h>
00025 #include "autonlist.h"
00026 #include "kernel.h"
00027
00028 #include <net-snmp/net-snmp-includes.h>
00029 #include <net-snmp/agent/ds_agent.h>
00030
00031 struct autonlist *nlists = 0;
00032 static void init_nlist(struct nlist *);
00033
00034 long
00035 auto_nlist_value(const char *string)
00036 {
00037 struct autonlist **ptr, *it = 0;
00038 int cmp;
00039
00040 if (string == 0)
00041 return 0;
00042
00043 ptr = &nlists;
00044 while (*ptr != 0 && it == 0) {
00045 cmp = strcmp((*ptr)->symbol, string);
00046 if (cmp == 0)
00047 it = *ptr;
00048 else if (cmp < 0) {
00049 ptr = &((*ptr)->left);
00050 } else {
00051 ptr = &((*ptr)->right);
00052 }
00053 }
00054 if (*ptr == 0) {
00055 *ptr = (struct autonlist *) malloc(sizeof(struct autonlist));
00056 it = *ptr;
00057 it->left = 0;
00058 it->right = 0;
00059 it->symbol = (char *) malloc(strlen(string) + 1);
00060 strcpy(it->symbol, string);
00061
00062
00063
00064 it->nl[0].n_name = (char *) malloc(strlen(string) + 2);
00065 #ifdef aix4
00066 strcpy(it->nl[0].n_name, string);
00067 #else
00068 sprintf(it->nl[0].n_name, "_%s", string);
00069 #endif
00070 it->nl[1].n_name = 0;
00071 init_nlist(it->nl);
00072 #ifndef aix4
00073 if (it->nl[0].n_type == 0) {
00074 strcpy(it->nl[0].n_name, string);
00075 init_nlist(it->nl);
00076 }
00077 #endif
00078 if (it->nl[0].n_type == 0) {
00079 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00080 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00081 snmp_log(LOG_ERR, "nlist err: neither %s nor _%s found.\n",
00082 string, string);
00083 }
00084 return (-1);
00085 } else {
00086 DEBUGMSGTL(("auto_nlist", "nlist: found symbol %s at %x.\n",
00087 it->symbol, it->nl[0].n_value));
00088 return (it->nl[0].n_value);
00089 }
00090 } else
00091 return (it->nl[0].n_value);
00092 }
00093
00094 int
00095 auto_nlist(const char *string, char *var, int size)
00096 {
00097 long result;
00098 int ret;
00099 result = auto_nlist_value(string);
00100 if (result != -1) {
00101 if (var != NULL) {
00102 ret = klookup(result, var, size);
00103 if (!ret)
00104 snmp_log(LOG_ERR,
00105 "auto_nlist failed on %s at location %lx\n",
00106 string, result);
00107 return ret;
00108 } else
00109 return 1;
00110 }
00111 return 0;
00112 }
00113
00114 static void
00115 init_nlist(struct nlist nl[])
00116 {
00117 #ifdef CAN_USE_NLIST
00118 int ret;
00119 #if HAVE_KVM_OPENFILES
00120 kvm_t *kernel;
00121 char kvm_errbuf[4096];
00122
00123 if ((kernel = kvm_openfiles(KERNEL_LOC, NULL, NULL, O_RDONLY, kvm_errbuf))
00124 == NULL) {
00125 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00126 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00127 return;
00128 } else {
00129 snmp_log_perror("kvm_openfiles");
00130 snmp_log(LOG_ERR, "kvm_openfiles: %s\n", kvm_errbuf);
00131 exit(1);
00132 }
00133 }
00134 if ((ret = kvm_nlist(kernel, nl)) == -1) {
00135 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00136 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00137 return;
00138 } else {
00139 snmp_log_perror("kvm_nlist");
00140 exit(1);
00141 }
00142 }
00143 kvm_close(kernel);
00144 #else
00145 #if defined(aix4) && defined(HAVE_KNLIST)
00146 if (knlist(nl, 1, sizeof(struct nlist)) == -1) {
00147 DEBUGMSGTL(("auto_nlist", "knlist failed on symbol: %s\n",
00148 nl[0].n_name));
00149 if (errno == EFAULT) {
00150 nl[0].n_type = 0;
00151 nl[0].n_value = 0;
00152 } else {
00153 snmp_log_perror("knlist");
00154 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00155 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00156 return;
00157 } else {
00158 exit(1);
00159 }
00160 }
00161 }
00162 #else
00163 if ((ret = nlist(KERNEL_LOC, nl)) == -1) {
00164 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00165 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00166 return;
00167 } else {
00168 snmp_log_perror("nlist");
00169 exit(1);
00170 }
00171 }
00172 #endif
00173 #endif
00174 for (ret = 0; nl[ret].n_name != NULL; ret++) {
00175 #ifdef aix4
00176 if (nl[ret].n_type == 0 && nl[ret].n_value != 0)
00177 nl[ret].n_type = 1;
00178 #endif
00179 if (nl[ret].n_type == 0) {
00180 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00181 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00182 DEBUGMSGTL(("auto_nlist", "nlist err: %s not found\n",
00183 nl[ret].n_name));
00184 }
00185 } else {
00186 DEBUGMSGTL(("auto_nlist", "nlist: %s 0x%X\n", nl[ret].n_name,
00187 (unsigned int) nl[ret].n_value));
00188 }
00189 }
00190 #endif
00191 }
00192
00193 int
00194 KNLookup(struct nlist nl[], int nl_which, char *buf, int s)
00195 {
00196 struct nlist *nlp = &nl[nl_which];
00197
00198 if (nlp->n_value == 0) {
00199 snmp_log(LOG_ERR, "Accessing non-nlisted variable: %s\n",
00200 nlp->n_name);
00201 nlp->n_value = -1;
00202 return 0;
00203 }
00204 if (nlp->n_value == -1)
00205 return 0;
00206
00207 return klookup(nlp->n_value, buf, s);
00208 }
00209
00210 #ifdef TESTING
00211 void
00212 auto_nlist_print_tree(int indent, struct autonlist *ptr)
00213 {
00214 char buf[1024];
00215 if (indent == -2) {
00216 snmp_log(LOG_ERR, "nlist tree:\n");
00217 auto_nlist_print_tree(12, nlists);
00218 } else {
00219 if (ptr == 0)
00220 return;
00221 sprintf(buf, "%%%ds\n", indent);
00222
00223
00224
00225 DEBUGMSGTL(("auto_nlist", buf, ptr->symbol));
00226 auto_nlist_print_tree(indent + 2, ptr->left);
00227 auto_nlist_print_tree(indent + 2, ptr->right);
00228 }
00229 }
00230 #endif
00231 #else
00232 #include <net-snmp/agent/auto_nlist.h>
00233 int
00234 auto_nlist_noop(void)
00235 {
00236 return 0;
00237 }
00238 #endif