net-snmp 5.7
auto_nlist.c
00001 #include <net-snmp/net-snmp-config.h>
00002 
00003 #ifdef NETSNMP_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          * allocate an extra byte for inclusion of a preceding '_' later 
00063          */
00064         it->nl[0].n_name = (char *) malloc(strlen(string) + 2);
00065 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
00066         strcpy(it->nl[0].n_name, string);
00067         it->nl[0].n_name[strlen(string)+1] = '\0';
00068 #else
00069         sprintf(it->nl[0].n_name, "_%s", string);
00070 #endif
00071         it->nl[1].n_name = 0;
00072         init_nlist(it->nl);
00073 #if !(defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7) || \
00074                     defined(netbsd1) || defined(dragonfly)) 
00075         if (it->nl[0].n_type == 0) {
00076             strcpy(it->nl[0].n_name, string);
00077             it->nl[0].n_name[strlen(string)+1] = '\0';
00078             init_nlist(it->nl);
00079         }
00080 #endif
00081         if (it->nl[0].n_type == 0) {
00082             if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00083                                         NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00084                 snmp_log(LOG_ERR, "nlist err: neither %s nor _%s found.\n",
00085                          string, string);
00086             }
00087             return (-1);
00088         } else {
00089             DEBUGMSGTL(("auto_nlist:auto_nlist_value", "found symbol %s at %x.\n",
00090                         it->symbol, it->nl[0].n_value));
00091             return (it->nl[0].n_value);
00092         }
00093     } else
00094         return (it->nl[0].n_value);
00095 }
00096 
00097 int
00098 auto_nlist(const char *string, char *var, int size)
00099 {
00100     long            result;
00101     int             ret;
00102     result = auto_nlist_value(string);
00103     if (result != -1) {
00104         if (var != NULL) {
00105             ret = klookup(result, var, size);
00106             if (!ret)
00107                 snmp_log(LOG_ERR,
00108                          "auto_nlist failed on %s at location %lx\n",
00109                          string, result);
00110             return ret;
00111         } else
00112             return 1;
00113     }
00114     return 0;
00115 }
00116 
00117 static void
00118 init_nlist(struct nlist nl[])
00119 {
00120     int             ret;
00121 #if HAVE_KVM_OPENFILES
00122     kvm_t          *kernel;
00123     char            kvm_errbuf[4096];
00124 
00125     if ((kernel = kvm_openfiles(KERNEL_LOC, NULL, NULL, O_RDONLY, kvm_errbuf))
00126         == NULL) {
00127         if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00128                                    NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00129             return;
00130         } else {
00131             snmp_log_perror("kvm_openfiles");
00132             snmp_log(LOG_ERR, "kvm_openfiles: %s\n", kvm_errbuf);
00133             exit(1);
00134         }
00135     }
00136     if ((ret = kvm_nlist(kernel, nl)) == -1) {
00137         if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00138                                    NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00139             return;
00140         } else {
00141             snmp_log_perror("kvm_nlist");
00142             exit(1);
00143         }
00144     }
00145     kvm_close(kernel);
00146 #else                           /* ! HAVE_KVM_OPENFILES */
00147 #if (defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)) && defined(HAVE_KNLIST)
00148     if (knlist(nl, 1, sizeof(struct nlist)) == -1) {
00149         DEBUGMSGTL(("auto_nlist:init_nlist", "knlist failed on symbol:  %s\n",
00150                     nl[0].n_name));
00151         if (errno == EFAULT) {
00152             nl[0].n_type = 0;
00153             nl[0].n_value = 0;
00154         } else {
00155             snmp_log_perror("knlist");
00156             if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00157                                        NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00158                 return;
00159             } else {
00160                 exit(1);
00161             }
00162         }
00163     }
00164 #else
00165     if ((ret = nlist(KERNEL_LOC, nl)) == -1) {
00166         if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00167                                    NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00168             return;
00169         } else {
00170             snmp_log_perror("nlist");
00171             exit(1);
00172         }
00173     }
00174 #endif                          /*aix4 */
00175 #endif                          /* ! HAVE_KVM_OPENFILES */
00176     for (ret = 0; nl[ret].n_name != NULL; ret++) {
00177 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
00178         if (nl[ret].n_type == 0 && nl[ret].n_value != 0)
00179             nl[ret].n_type = 1;
00180 #endif
00181         if (nl[ret].n_type == 0) {
00182             if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00183                                         NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
00184                 DEBUGMSGTL(("auto_nlist:init_nlist", "nlist err:  %s not found\n",
00185                             nl[ret].n_name));
00186             }
00187         } else {
00188             DEBUGMSGTL(("auto_nlist:init_nlist", "nlist: %s 0x%X\n", nl[ret].n_name,
00189                         (unsigned int) nl[ret].n_value));
00190         }
00191     }
00192 }
00193 
00194 int
00195 KNLookup(struct nlist nl[], int nl_which, char *buf, int s)
00196 {
00197     struct nlist   *nlp = &nl[nl_which];
00198 
00199     if (nlp->n_value == 0) {
00200         snmp_log(LOG_ERR, "Accessing non-nlisted variable: %s\n",
00201                  nlp->n_name);
00202         nlp->n_value = -1;      /* only one error message ... */
00203         return 0;
00204     }
00205     if (nlp->n_value == -1)
00206         return 0;
00207 
00208     return klookup(nlp->n_value, buf, s);
00209 }
00210 
00211 #ifdef TESTING
00212 void
00213 auto_nlist_print_tree(int indent, struct autonlist *ptr)
00214 {
00215     char            buf[1024];
00216     if (indent == -2) {
00217         snmp_log(LOG_ERR, "nlist tree:\n");
00218         auto_nlist_print_tree(12, nlists);
00219     } else {
00220         if (ptr == 0)
00221             return;
00222         sprintf(buf, "%%%ds\n", indent);
00223         /*
00224          * DEBUGMSGTL(("auto_nlist", "buf: %s\n",buf)); 
00225          */
00226         DEBUGMSGTL(("auto_nlist", buf, ptr->symbol));
00227         auto_nlist_print_tree(indent + 2, ptr->left);
00228         auto_nlist_print_tree(indent + 2, ptr->right);
00229     }
00230 }
00231 #endif
00232 #else                           /* !NETSNMP_CAN_USE_NLIST */
00233 #include <net-snmp/agent/auto_nlist.h>
00234 int
00235 auto_nlist_noop(void)
00236 {
00237     return 0;
00238 }
00239 #endif                          /* NETSNMP_CAN_USE_NLIST */