Print this page
NEX-18763 net-snmp service could go into maintenance, if there are hundreds of FMA cases (fix lint)
NEX-18763 net-snmp service could go into maintenance, if there are hundreds of FMA cases
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-18680 snmpd core dumped
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Alexander Eremin <alexander.eremin@nexenta.com>
NEX-18695 libfmd_snmp is unable to handle multiple OIDs in GET request
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17796 libfmd_snmp performance is awful
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17938 libfmd_snmp dumps core in problem_lookup_uuid_exact()
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17829 libfmd_snmp and snmp-notify should provide FMRIs for all fault types
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-17777 snmptable produces bogus output for FM tables
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-17772 libfmd_snmp should learn about new FmProblem fields
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-3125 libfmd_snmp should compile with newer net-snmp
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/fm/libfmd_snmp/common/problem.c
+++ new/usr/src/lib/fm/libfmd_snmp/common/problem.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 +/*
28 + * Copyright 2019 Nexenta Systems, Inc.
29 + */
30 +
27 31 #include <sys/fm/protocol.h>
32 +
28 33 #include <fm/fmd_adm.h>
29 34 #include <fm/fmd_snmp.h>
35 +#include <fm/libfmevent.h>
36 +#include <fm/libtopo.h>
37 +
30 38 #include <net-snmp/net-snmp-config.h>
31 39 #include <net-snmp/net-snmp-includes.h>
32 40 #include <net-snmp/agent/net-snmp-agent-includes.h>
33 -#include <pthread.h>
34 -#include <stddef.h>
35 -#include <errno.h>
41 +
36 42 #include <alloca.h>
37 -#include <locale.h>
38 -#include <libuutil.h>
43 +#include <errno.h>
39 44 #include <libnvpair.h>
45 +#include <libuutil.h>
46 +#include <locale.h>
47 +#include <netdb.h>
48 +#include <pthread.h>
49 +#include <stddef.h>
50 +
40 51 #include "sunFM_impl.h"
41 52 #include "problem.h"
42 53
43 54 /*
44 55 * We assume that the number of suspect fault events associated with a
45 56 * particular case will generally be sufficiently small that the overhead
46 57 * associated with indexing them in a tree would exceed the gain from
47 58 * not traversing the fault list for each request.
48 59 */
49 -static uu_avl_pool_t *problem_uuid_avl_pool;
50 -static uu_avl_t *problem_uuid_avl;
60 +static uu_avl_pool_t *problem_uuid_avl_pool = NULL;
61 +static uu_avl_t *problem_uuid_avl = NULL;
51 62
52 63 #define VALID_AVL_STATE (problem_uuid_avl_pool != NULL && \
53 64 problem_uuid_avl != NULL)
54 65
55 -#define UPDATE_WAIT_MILLIS 10 /* poll interval in milliseconds */
56 -
57 -/*
58 - * Update types. Single-index and all are mutually exclusive.
59 - */
60 -#define UCT_INDEX 0x1
61 -#define UCT_ALL 0x2
62 -#define UCT_FLAGS 0x3
63 -
64 -/*
65 - * Locking strategy is described in module.c.
66 - */
67 66 static int valid_stamp;
68 67 static pthread_mutex_t update_lock;
69 68 static pthread_cond_t update_cv;
70 -static volatile enum { US_QUIET, US_NEEDED, US_INPROGRESS } update_status;
69 +static fmev_shdl_t evhdl;
71 70
72 71 static Netsnmp_Node_Handler sunFmProblemTable_handler;
73 72 static Netsnmp_Node_Handler sunFmFaultEventTable_handler;
74 73
74 +static char *
75 +nvl2fmri(nvlist_t *nvl)
76 +{
77 + topo_hdl_t *thp;
78 + int topoerr;
79 + char *fmri, *ret = NULL;
80 +
81 + thp = topo_open(TOPO_VERSION, NULL, &topoerr);
82 + if (thp == NULL)
83 + return (NULL);
84 +
85 + if (topo_fmri_nvl2str(thp, nvl, &fmri, &topoerr) == 0) {
86 + ret = strdup(fmri);
87 + topo_hdl_strfree(thp, fmri);
88 + }
89 +
90 + topo_close(thp);
91 + return (ret);
92 +}
93 +
75 94 static sunFmProblem_data_t *
76 95 problem_key_build(const char *uuid)
77 96 {
78 97 static sunFmProblem_data_t key;
79 98
80 99 key.d_aci_uuid = uuid;
81 100
82 101 return (&key);
83 102 }
84 103
85 104 static sunFmProblem_data_t *
86 105 problem_lookup_uuid_exact(const char *uuid)
87 106 {
88 107 sunFmProblem_data_t *key, *data;
89 108
90 109 key = problem_key_build(uuid);
91 110
92 111 DEBUGMSGTL((MODNAME_STR, "lookup_exact for uuid %s\n", uuid));
93 112 data = uu_avl_find(problem_uuid_avl, key, NULL, NULL);
94 113
95 114 return (data);
96 115 }
97 116
98 117 static sunFmProblem_data_t *
99 118 problem_lookup_uuid_next(const char *uuid)
100 119 {
101 120 sunFmProblem_data_t *key, *data;
102 121 uu_avl_index_t idx;
103 122
104 123 key = problem_key_build(uuid);
105 124
106 125 DEBUGMSGTL((MODNAME_STR, "lookup_next for uuid %s\n", uuid));
107 126 (void) uu_avl_find(problem_uuid_avl, key, NULL, &idx);
108 127
109 128 data = uu_avl_nearest_next(problem_uuid_avl, idx);
110 129
111 130 DEBUGMSGTL((MODNAME_STR, "lookup_next: entry is %p\n", data));
112 131
113 132 return (data);
114 133 }
115 134
116 135 static sunFmFaultEvent_data_t *
117 136 faultevent_lookup_index_exact(sunFmProblem_data_t *data, ulong_t index)
118 137 {
119 138 if (index > data->d_nsuspects)
120 139 return (NULL);
121 140
122 141 if (data->d_suspects == NULL)
123 142 return (NULL);
124 143
125 144 return (data->d_suspects[index - 1]);
126 145 }
127 146
128 147 static sunFmFaultStatus_data_t
129 148 faultstatus_lookup_index_exact(sunFmProblem_data_t *data, ulong_t index)
130 149 {
131 150 if (index > data->d_nsuspects)
132 151 return (0);
|
↓ open down ↓ |
48 lines elided |
↑ open up ↑ |
133 152
134 153 if (data->d_statuses == NULL)
135 154 return (0);
136 155
137 156 if (data->d_valid != valid_stamp)
138 157 return (0);
139 158
140 159 return (data->d_statuses[index - 1]);
141 160 }
142 161
162 +#define FM_SUSPECT_SKIP \
163 + (FM_SUSPECT_NOT_PRESENT | FM_SUSPECT_REPAIRED | \
164 + FM_SUSPECT_REPLACED | FM_SUSPECT_ACQUITTED)
165 +
143 166 /*ARGSUSED*/
144 167 static int
145 168 problem_update_one(const fmd_adm_caseinfo_t *acp, void *arg)
146 169 {
147 170 sunFmProblem_data_t *data;
148 171 nvlist_t *nvl;
149 172 int64_t *diag_time;
150 173 uint_t nelem;
151 - uint32_t nsusp;
152 174 int err;
175 + int i;
176 + int cr = 0;
177 + uint8_t *statuses;
153 178
154 - DEBUGMSGTL((MODNAME_STR, "update_one\n"));
155 -
156 179 ASSERT(acp->aci_uuid != NULL);
157 180
158 181 if ((data = problem_lookup_uuid_exact(acp->aci_uuid)) == NULL) {
159 182 uu_avl_index_t idx;
183 + nvlist_t **fnvl;
184 + nvlist_t *snvl;
185 + uint_t nnvl;
160 186
187 + /* Lookup statuses early so we could skip resolved problems */
188 + if (nvlist_lookup_uint8_array(acp->aci_event,
189 + FM_SUSPECT_FAULT_STATUS, &statuses, &nelem) != 0)
190 + return (0);
191 +
192 + for (i = 0; i < nelem; i++) {
193 + if (statuses[i] & FM_SUSPECT_SKIP)
194 + cr++;
195 + }
196 + if (cr == nelem) {
197 + DEBUGMSGTL((MODNAME_STR,
198 + "problem %s is resolved, skipping\n",
199 + acp->aci_uuid));
200 + return (0);
201 + }
202 +
161 203 DEBUGMSGTL((MODNAME_STR, "found new problem %s\n",
162 204 acp->aci_uuid));
163 205 if ((data = SNMP_MALLOC_TYPEDEF(sunFmProblem_data_t)) == NULL) {
164 - (void) snmp_log(LOG_ERR, MODNAME_STR ": Out of memory "
165 - "for new problem data at %s:%d\n", __FILE__,
166 - __LINE__);
206 + (void) snmp_log(LOG_ERR, MODNAME_STR
207 + ": out of memory for new problem data\n");
167 208 return (0);
168 209 }
169 210 if ((err = nvlist_dup(acp->aci_event, &data->d_aci_event, 0))
170 211 != 0) {
171 - (void) snmp_log(LOG_ERR, MODNAME_STR ": Problem data "
172 - "setup failed: %s\n", strerror(err));
212 + (void) snmp_log(LOG_ERR, MODNAME_STR
213 + ": problem data setup failed: %s\n", strerror(err));
173 214 SNMP_FREE(data);
174 215 return (0);
175 216 }
176 217
177 - data->d_aci_uuid = data->d_aci_code = data->d_aci_url = "-";
218 + data->d_aci_uuid = data->d_aci_code = data->d_aci_type =
219 + data->d_aci_severity = data->d_aci_url =
220 + data->d_aci_desc = "-";
178 221 (void) nvlist_lookup_string(data->d_aci_event, FM_SUSPECT_UUID,
179 222 (char **)&data->d_aci_uuid);
180 223 (void) nvlist_lookup_string(data->d_aci_event,
181 224 FM_SUSPECT_DIAG_CODE, (char **)&data->d_aci_code);
182 - data->d_aci_url = strdup(acp->aci_url);
225 + (void) nvlist_lookup_string(data->d_aci_event,
226 + FM_SUSPECT_TYPE, (char **)&data->d_aci_type);
227 + (void) nvlist_lookup_string(data->d_aci_event,
228 + FM_SUSPECT_SEVERITY, (char **)&data->d_aci_severity);
229 + if (acp->aci_url != NULL)
230 + data->d_aci_url = strdup(acp->aci_url);
231 + (void) nvlist_lookup_string(data->d_aci_event,
232 + FM_SUSPECT_DESC, (char **)&data->d_aci_desc);
183 233
234 + /*
235 + * NOTE: This should match the logic in libfmnotify.
236 + *
237 + * Extract the fault-list, and use the following order
238 + * of nested nvlists from its first element to make up FMRI:
239 + * - FRU
240 + * - ASRU
241 + * - resource
242 + */
243 + if (nvlist_lookup_nvlist_array(data->d_aci_event,
244 + FM_SUSPECT_FAULT_LIST, &fnvl, &nnvl) == 0 && nnvl == 1 &&
245 + (nvlist_lookup_nvlist(fnvl[0], FM_FAULT_FRU, &snvl) == 0 ||
246 + nvlist_lookup_nvlist(fnvl[0], FM_FAULT_ASRU, &snvl) == 0 ||
247 + nvlist_lookup_nvlist(fnvl[0], FM_FAULT_RESOURCE,
248 + &snvl) == 0))
249 + data->d_aci_fmri = nvl2fmri(snvl);
250 + if (data->d_aci_fmri == NULL)
251 + data->d_aci_fmri = "-";
252 +
184 253 if (nvlist_lookup_nvlist(data->d_aci_event, FM_SUSPECT_DE,
185 254 &nvl) == 0)
186 - if ((data->d_diag_engine = sunFm_nvl2str(nvl)) == NULL)
187 - data->d_diag_engine = "-";
255 + data->d_diag_engine = nvl2fmri(nvl);
256 + if (data->d_diag_engine == NULL)
257 + data->d_diag_engine = "-";
188 258
189 259 if (nvlist_lookup_int64_array(data->d_aci_event,
190 260 FM_SUSPECT_DIAG_TIME, &diag_time, &nelem) == 0 &&
191 261 nelem >= 2) {
192 262 data->d_diag_time.tv_sec = (long)diag_time[0];
193 263 data->d_diag_time.tv_usec = (long)diag_time[1];
194 264 }
195 265
196 266 (void) nvlist_lookup_uint32(data->d_aci_event,
197 - FM_SUSPECT_FAULT_SZ, &nsusp);
198 - data->d_nsuspects = (ulong_t)nsusp;
199 -
267 + FM_SUSPECT_FAULT_SZ, &data->d_nsuspects);
200 268 (void) nvlist_lookup_nvlist_array(data->d_aci_event,
201 269 FM_SUSPECT_FAULT_LIST, &data->d_suspects, &nelem);
202 -
203 - ASSERT(nelem == data->d_nsuspects);
204 -
205 270 (void) nvlist_lookup_uint8_array(data->d_aci_event,
206 271 FM_SUSPECT_FAULT_STATUS, &data->d_statuses, &nelem);
207 272
208 - ASSERT(nelem == data->d_nsuspects);
209 -
210 273 uu_avl_node_init(data, &data->d_uuid_avl,
211 274 problem_uuid_avl_pool);
212 275 (void) uu_avl_find(problem_uuid_avl, data, NULL, &idx);
213 276 uu_avl_insert(problem_uuid_avl, data, idx);
214 277
215 278 data->d_valid = valid_stamp;
216 279
217 280 DEBUGMSGTL((MODNAME_STR, "completed new problem %s@%p\n",
218 281 data->d_aci_uuid, data));
219 282 } else {
220 - uint8_t *statuses;
221 - int i;
283 + if (nvlist_lookup_uint8_array(acp->aci_event,
284 + FM_SUSPECT_FAULT_STATUS, &statuses, &nelem) != 0)
285 + return (0);
222 286
223 - (void) nvlist_lookup_uint8_array(acp->aci_event,
224 - FM_SUSPECT_FAULT_STATUS, &statuses, &nelem);
287 + if (nelem != data->d_nsuspects) {
288 + DEBUGMSGTL((MODNAME_STR,
289 + "problem %s is malformed; deleting\n",
290 + data->d_aci_uuid));
291 + goto delete;
292 + }
225 293
226 - ASSERT(nelem == data->d_nsuspects);
227 -
228 - for (i = 0; i < nelem; i++)
294 + for (i = 0; i < nelem; i++) {
295 + if (statuses[i] & FM_SUSPECT_SKIP)
296 + cr++;
229 297 data->d_statuses[i] = statuses[i];
230 -
231 - data->d_valid = valid_stamp;
298 + }
299 + if (cr == nelem) {
300 + DEBUGMSGTL((MODNAME_STR,
301 + "problem %s is now resolved; deleting\n",
302 + data->d_aci_uuid));
303 + goto delete;
304 + } else {
305 + data->d_valid = valid_stamp;
306 + }
232 307 }
233 308
234 - /*
235 - * We don't touch problems we've seen before; they shouldn't change
236 - * in any way we care about, since they've already been solved. The
237 - * state, however, could change, and if we later expose that to the
238 - * client we need to update it here.
239 - */
309 + return (0);
240 310
311 +delete:
312 + uu_avl_remove(problem_uuid_avl, data);
313 + uu_avl_node_fini(data, &data->d_uuid_avl,
314 + problem_uuid_avl_pool);
315 + nvlist_free(data->d_aci_event);
316 + SNMP_FREE(data);
241 317 return (0);
242 318 }
243 319
244 -static int
245 -problem_update(sunFmProblem_update_ctx_t *update_ctx)
320 +/*ARGSUSED*/
321 +static void *
322 +update_thread(void *arg)
246 323 {
247 324 fmd_adm_t *adm;
325 + static struct timespec tv;
248 326
249 - ASSERT(update_ctx != NULL);
250 - ASSERT((update_ctx->uc_type & (UCT_INDEX|UCT_ALL)) !=
251 - (UCT_INDEX|UCT_ALL));
252 - ASSERT((update_ctx->uc_type & ~UCT_FLAGS) == 0);
253 - ASSERT(VALID_AVL_STATE);
327 + /* Do a 1-minute checks for changes */
328 + tv.tv_sec = 60;
329 + tv.tv_nsec = 0;
254 330
255 - if ((adm = fmd_adm_open(update_ctx->uc_host, update_ctx->uc_prog,
256 - update_ctx->uc_version)) == NULL) {
257 - (void) snmp_log(LOG_ERR, MODNAME_STR ": Communication with fmd "
258 - "failed: %s\n", strerror(errno));
259 - return (SNMP_ERR_RESOURCEUNAVAILABLE);
260 - }
331 + for (;;) {
332 + ASSERT(VALID_AVL_STATE);
261 333
262 - ++valid_stamp;
263 - if (fmd_adm_case_iter(adm, SNMP_URL_MSG, problem_update_one,
264 - update_ctx) != 0) {
265 - (void) snmp_log(LOG_ERR, MODNAME_STR ": fmd case information "
266 - "update failed: %s\n", fmd_adm_errmsg(adm));
267 - fmd_adm_close(adm);
268 - return (SNMP_ERR_RESOURCEUNAVAILABLE);
269 - }
334 + (void) pthread_mutex_lock(&update_lock);
335 + /* We don't care if we were awaken explicitly or by timeout */
336 + (void) pthread_cond_reltimedwait_np(&update_cv, &update_lock,
337 + &tv);
338 + if ((adm = fmd_adm_open(NULL, FMD_ADM_PROGRAM,
339 + FMD_ADM_VERSION)) == NULL) {
340 + (void) pthread_mutex_unlock(&update_lock);
341 + (void) snmp_log(LOG_ERR, MODNAME_STR
342 + ": communication with fmd failed: %s\n",
343 + strerror(errno));
344 + continue;
345 + }
270 346
271 - DEBUGMSGTL((MODNAME_STR, "case iteration completed\n"));
347 + valid_stamp++;
272 348
273 - fmd_adm_close(adm);
274 - return (SNMP_ERR_NOERROR);
275 -}
349 + DEBUGMSGTL((MODNAME_STR, "case iteration started\n"));
350 + if (fmd_adm_case_iter(adm, SNMP_URL_MSG, problem_update_one,
351 + NULL) != 0) {
352 + (void) pthread_mutex_unlock(&update_lock);
353 + (void) snmp_log(LOG_ERR, MODNAME_STR
354 + ": fmd case information update failed: %s\n",
355 + fmd_adm_errmsg(adm));
356 + fmd_adm_close(adm);
357 + continue;
358 + }
276 359
277 -/*ARGSUSED*/
278 -static void
279 -update_thread(void *arg)
280 -{
281 - /*
282 - * The current problem_update implementation offers minimal savings
283 - * for the use of index-only updates; therefore we always do a full
284 - * update. If it becomes advantageous to limit updates to a single
285 - * index, the contexts can be queued by the handler instead.
286 - */
287 - sunFmProblem_update_ctx_t uc;
288 -
289 - uc.uc_host = NULL;
290 - uc.uc_prog = FMD_ADM_PROGRAM;
291 - uc.uc_version = FMD_ADM_VERSION;
292 -
293 - uc.uc_index = NULL;
294 - uc.uc_type = UCT_ALL;
295 -
296 - for (;;) {
297 - (void) pthread_mutex_lock(&update_lock);
298 - update_status = US_QUIET;
299 - while (update_status == US_QUIET)
300 - (void) pthread_cond_wait(&update_cv, &update_lock);
301 - update_status = US_INPROGRESS;
360 + fmd_adm_close(adm);
302 361 (void) pthread_mutex_unlock(&update_lock);
303 - (void) problem_update(&uc);
362 +
363 + DEBUGMSGTL((MODNAME_STR, "case iteration completed\n"));
304 364 }
365 +
366 + /*NOTREACHED*/
367 + return (NULL);
305 368 }
306 369
370 +/*ARGSUSED*/
307 371 static void
308 -request_update(void)
372 +event_cb(fmev_t ev, const char *class, nvlist_t *nvl, void *arg)
309 373 {
310 374 (void) pthread_mutex_lock(&update_lock);
311 - if (update_status != US_QUIET) {
312 - (void) pthread_mutex_unlock(&update_lock);
313 - return;
314 - }
315 - update_status = US_NEEDED;
316 375 (void) pthread_cond_signal(&update_cv);
317 376 (void) pthread_mutex_unlock(&update_lock);
318 377 }
319 378
320 379 /*ARGSUSED*/
321 380 static int
322 381 problem_compare_uuid(const void *l, const void *r, void *private)
323 382 {
324 383 sunFmProblem_data_t *l_data = (sunFmProblem_data_t *)l;
325 384 sunFmProblem_data_t *r_data = (sunFmProblem_data_t *)r;
326 385
327 386 ASSERT(l_data != NULL && r_data != NULL);
328 387
329 388 return (strcmp(l_data->d_aci_uuid, r_data->d_aci_uuid));
330 389 }
331 390
332 -int
333 -sunFmProblemTable_init(void)
391 +/* ARGSUSED */
392 +void *
393 +pid_thread(void *arg)
334 394 {
335 - static oid sunFmProblemTable_oid[] = { SUNFMPROBLEMTABLE_OID };
336 - netsnmp_table_registration_info *table_info;
337 - netsnmp_handler_registration *handler;
338 - int err;
395 + pid_t pid = getpid();
396 + int wait = 0;
339 397
340 - if ((err = pthread_mutex_init(&update_lock, NULL)) != 0) {
341 - (void) snmp_log(LOG_ERR, MODNAME_STR ": mutex_init failure: "
342 - "%s\n", strerror(err));
343 - return (MIB_REGISTRATION_FAILED);
344 - }
345 - if ((err = pthread_cond_init(&update_cv, NULL)) != 0) {
346 - (void) snmp_log(LOG_ERR, MODNAME_STR ": cond_init failure: "
347 - "%s\n", strerror(err));
348 - return (MIB_REGISTRATION_FAILED);
349 - }
350 -
351 - if ((err = pthread_create(NULL, NULL, (void *(*)(void *))update_thread,
352 - NULL)) != 0) {
353 - (void) snmp_log(LOG_ERR, MODNAME_STR ": error creating update "
354 - "thread: %s\n", strerror(err));
355 - return (MIB_REGISTRATION_FAILED);
356 - }
357 -
358 - if ((table_info =
359 - SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL)
360 - return (MIB_REGISTRATION_FAILED);
361 -
362 - if ((handler = netsnmp_create_handler_registration("sunFmProblemTable",
363 - sunFmProblemTable_handler, sunFmProblemTable_oid,
364 - OID_LENGTH(sunFmProblemTable_oid), HANDLER_CAN_RONLY)) == NULL) {
365 - SNMP_FREE(table_info);
366 - return (MIB_REGISTRATION_FAILED);
367 - }
368 -
369 398 /*
370 - * The Net-SNMP template uses add_indexes here, but that
371 - * function is unsafe because it does not check for failure.
399 + * Workaround the forking madness in net-snmp -- we need to
400 + * subscribe from the *forked* process so that event notifications
401 + * get our PID correctly.
402 + *
403 + * We also limit the wait to arbitrary long time of 10 seconds so that
404 + * we subscribe to event notifications when running with -f (don't fork)
405 + * specified.
372 406 */
373 - if (netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR) == NULL) {
374 - SNMP_FREE(table_info);
375 - SNMP_FREE(handler);
376 - return (MIB_REGISTRATION_FAILED);
407 + for (;;) {
408 + if (getpid() != pid || wait == 10) {
409 + /* Subscribe to fault event notifications */
410 + evhdl = fmev_shdl_init(LIBFMEVENT_VERSION_2, NULL, NULL,
411 + NULL);
412 + (void) fmev_shdl_subscribe(evhdl, "list.*", event_cb,
413 + NULL);
414 + break;
415 + }
416 + wait++;
417 + (void) sleep(1);
377 418 }
378 419
379 - table_info->min_column = SUNFMPROBLEM_COLMIN;
380 - table_info->max_column = SUNFMPROBLEM_COLMAX;
381 -
382 - if ((problem_uuid_avl_pool = uu_avl_pool_create("problem_uuid",
383 - sizeof (sunFmProblem_data_t),
384 - offsetof(sunFmProblem_data_t, d_uuid_avl), problem_compare_uuid,
385 - UU_AVL_DEBUG)) == NULL) {
386 - (void) snmp_log(LOG_ERR, MODNAME_STR ": problem_uuid avl pool "
387 - "creation failed: %s\n", uu_strerror(uu_error()));
388 - snmp_free_varbind(table_info->indexes);
389 - SNMP_FREE(table_info);
390 - SNMP_FREE(handler);
391 - return (MIB_REGISTRATION_FAILED);
392 - }
393 -
394 - if ((problem_uuid_avl = uu_avl_create(problem_uuid_avl_pool, NULL,
395 - UU_AVL_DEBUG)) == NULL) {
396 - (void) snmp_log(LOG_ERR, MODNAME_STR ": problem_uuid avl "
397 - "creation failed: %s\n", uu_strerror(uu_error()));
398 - snmp_free_varbind(table_info->indexes);
399 - SNMP_FREE(table_info);
400 - SNMP_FREE(handler);
401 - uu_avl_pool_destroy(problem_uuid_avl_pool);
402 - return (MIB_REGISTRATION_FAILED);
403 - }
404 -
405 - if ((err = netsnmp_register_table(handler, table_info)) !=
406 - MIB_REGISTERED_OK) {
407 - snmp_free_varbind(table_info->indexes);
408 - SNMP_FREE(table_info);
409 - SNMP_FREE(handler);
410 - uu_avl_destroy(problem_uuid_avl);
411 - uu_avl_pool_destroy(problem_uuid_avl_pool);
412 - return (err);
413 - }
414 -
415 - return (MIB_REGISTERED_OK);
420 + return (NULL);
416 421 }
417 422
418 423 int
419 -sunFmFaultEventTable_init(void)
424 +sunFmProblemTable_init(void)
420 425 {
421 426 static oid sunFmFaultEventTable_oid[] = { SUNFMFAULTEVENTTABLE_OID };
422 - netsnmp_table_registration_info *table_info;
423 - netsnmp_handler_registration *handler;
424 - int err;
427 + netsnmp_table_registration_info *ftinfo = NULL;
428 + netsnmp_handler_registration *fhandler = NULL;
429 + static oid sunFmProblemTable_oid[] = { SUNFMPROBLEMTABLE_OID };
430 + netsnmp_table_registration_info *ptinfo = NULL;
431 + netsnmp_handler_registration *phandler = NULL;
432 + pthread_t ptid;
433 + pthread_t utid;
434 + int ret = MIB_REGISTRATION_FAILED;
425 435
426 - if ((table_info =
427 - SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL)
428 - return (MIB_REGISTRATION_FAILED);
429 -
430 - if ((handler =
436 + /* Create fault event table and handler */
437 + if ((ftinfo =
438 + SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL ||
439 + netsnmp_table_helper_add_index(ftinfo, ASN_OCTET_STR) == NULL ||
440 + netsnmp_table_helper_add_index(ftinfo, ASN_UNSIGNED) == NULL ||
441 + (fhandler =
431 442 netsnmp_create_handler_registration("sunFmFaultEventTable",
432 443 sunFmFaultEventTable_handler, sunFmFaultEventTable_oid,
433 - OID_LENGTH(sunFmFaultEventTable_oid), HANDLER_CAN_RONLY)) == NULL) {
434 - SNMP_FREE(table_info);
435 - return (MIB_REGISTRATION_FAILED);
436 - }
444 + OID_LENGTH(sunFmFaultEventTable_oid), HANDLER_CAN_RONLY)) == NULL)
445 + goto fail;
437 446
438 - /*
439 - * The Net-SNMP template uses add_indexes here, but that
440 - * function is unsafe because it does not check for failure.
441 - */
442 - if (netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR) == NULL) {
443 - SNMP_FREE(table_info);
444 - SNMP_FREE(handler);
445 - return (MIB_REGISTRATION_FAILED);
446 - }
447 - if (netsnmp_table_helper_add_index(table_info, ASN_UNSIGNED) == NULL) {
448 - snmp_free_varbind(table_info->indexes);
449 - SNMP_FREE(table_info);
450 - SNMP_FREE(handler);
451 - return (MIB_REGISTRATION_FAILED);
452 - }
447 + ftinfo->min_column = SUNFMFAULTEVENT_COLMIN;
448 + ftinfo->max_column = SUNFMFAULTEVENT_COLMAX;
453 449
454 - table_info->min_column = SUNFMFAULTEVENT_COLMIN;
455 - table_info->max_column = SUNFMFAULTEVENT_COLMAX;
450 + /* Register fault event handler */
451 + if ((ret = netsnmp_register_table(fhandler, ftinfo)) !=
452 + MIB_REGISTERED_OK)
453 + goto fail;
456 454
457 - if ((err = netsnmp_register_table(handler, table_info)) !=
458 - MIB_REGISTERED_OK) {
459 - snmp_free_varbind(table_info->indexes);
460 - SNMP_FREE(table_info);
461 - SNMP_FREE(handler);
462 - return (err);
455 + /* Create problem table, data pool, and handler */
456 + if ((problem_uuid_avl_pool = uu_avl_pool_create("problem_uuid",
457 + sizeof (sunFmProblem_data_t), offsetof(sunFmProblem_data_t,
458 + d_uuid_avl), problem_compare_uuid, UU_AVL_DEBUG)) == NULL ||
459 + (problem_uuid_avl = uu_avl_create(problem_uuid_avl_pool, NULL,
460 + UU_AVL_DEBUG)) == NULL ||
461 + (ptinfo =
462 + SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL ||
463 + netsnmp_table_helper_add_index(ptinfo, ASN_OCTET_STR) == NULL ||
464 + (phandler =
465 + netsnmp_create_handler_registration("sunFmProblemTable",
466 + sunFmProblemTable_handler, sunFmProblemTable_oid,
467 + OID_LENGTH(sunFmProblemTable_oid), HANDLER_CAN_RONLY)) == NULL)
468 + goto fail;
469 +
470 + ptinfo->min_column = SUNFMPROBLEM_COLMIN;
471 + ptinfo->max_column = SUNFMPROBLEM_COLMAX;
472 +
473 + /* Register problem handler */
474 + if ((ret = netsnmp_register_table(phandler, ptinfo)) !=
475 + MIB_REGISTERED_OK)
476 + goto fail;
477 +
478 + /* Create PID change waiter thread */
479 + if (pthread_create(&ptid, NULL, pid_thread, 0) != 0) {
480 + (void) snmp_log(LOG_ERR, MODNAME_STR
481 + ": failed to create pid thread: %s\n", strerror(ret));
482 + goto fail;
463 483 }
464 484
485 + /* Create update thread */
486 + if ((ret = pthread_mutex_init(&update_lock, NULL)) != 0 ||
487 + (ret = pthread_cond_init(&update_cv, NULL)) != 0 ||
488 + (ret = pthread_create(&utid, NULL, update_thread, 0)) != 0) {
489 + (void) snmp_log(LOG_ERR, MODNAME_STR
490 + ": failed to create update thread: %s\n", strerror(ret));
491 + goto fail;
492 + }
493 +
465 494 return (MIB_REGISTERED_OK);
495 +
496 +fail:
497 + (void) pthread_mutex_destroy(&update_lock);
498 + if (problem_uuid_avl != NULL)
499 + uu_avl_destroy(problem_uuid_avl);
500 + if (problem_uuid_avl_pool != NULL)
501 + uu_avl_pool_destroy(problem_uuid_avl_pool);
502 + if (ftinfo->indexes != NULL)
503 + snmp_free_varbind(ftinfo->indexes);
504 + if (ftinfo != NULL)
505 + SNMP_FREE(ftinfo);
506 + if (ptinfo->indexes != NULL)
507 + snmp_free_varbind(ptinfo->indexes);
508 + if (ptinfo != NULL)
509 + SNMP_FREE(ptinfo);
510 + if (fhandler != NULL)
511 + SNMP_FREE(fhandler);
512 + if (phandler != NULL)
513 + SNMP_FREE(phandler);
514 +
515 + return (ret);
466 516 }
467 517
468 518 /*
469 519 * Returns the problem data for the problem whose uuid is next according
470 520 * to ASN.1 lexical ordering after the request in table_info. Indexes are
471 521 * updated to reflect the OID of the value being returned. This allows
472 522 * us to implement GETNEXT.
473 523 */
474 524 static sunFmProblem_data_t *
475 525 sunFmProblemTable_nextpr(netsnmp_handler_registration *reginfo,
476 526 netsnmp_table_request_info *table_info)
477 527 {
478 528 sunFmProblem_data_t *data;
479 529 char *uuid = "";
480 530
481 531 if (table_info->number_indexes < 1) {
482 532 oid tmpoid[MAX_OID_LEN];
483 533
484 534 DEBUGMSGTL((MODNAME_STR, "nextpr: no indexes given\n"));
485 535
486 536 snmp_free_varbind(table_info->indexes);
487 537 table_info->indexes =
488 538 SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
489 539 (void) snmp_set_var_typed_value(table_info->indexes,
490 540 ASN_OCTET_STR, (const uchar_t *)uuid, 0);
491 541 (void) memcpy(tmpoid, reginfo->rootoid,
492 542 reginfo->rootoid_len * sizeof (oid));
493 543 tmpoid[reginfo->rootoid_len] = 1;
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
494 544 tmpoid[reginfo->rootoid_len + 1] = table_info->colnum;
495 545 if (build_oid_segment(table_info->indexes) != SNMPERR_SUCCESS) {
496 546 snmp_free_varbind(table_info->indexes);
497 547 return (NULL);
498 548 }
499 549 table_info->number_indexes = 1;
500 550 table_info->index_oid_len = table_info->indexes->name_length;
501 551 (void) memcpy(table_info->index_oid, table_info->indexes->name,
502 552 table_info->indexes->name_length);
503 553
504 - DEBUGMSGTL((MODNAME_STR, "nextpr: built fake index:\n"));
554 + DEBUGMSGTL((MODNAME_STR, "nextpr: built fake index: "));
505 555 DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
506 556 DEBUGMSG((MODNAME_STR, "\n"));
507 557 } else {
508 558 /*
509 559 * Construct the next possible UUID to look for. We can
510 560 * simply increment the least significant byte of the last
511 561 * UUID because (a) that preserves SNMP lex order and (b)
512 562 * the characters that may appear in a UUID do not include
513 563 * 127 nor 255.
514 564 */
515 565 uuid = alloca(table_info->indexes->val_len + 1);
516 566 (void) strlcpy(uuid,
517 567 (const char *)table_info->indexes->val.string,
518 568 table_info->indexes->val_len + 1);
519 569 ++uuid[table_info->indexes->val_len - 1];
520 570
521 571 DEBUGMSGTL((MODNAME_STR, "nextpr: received index:\n"));
522 572 DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
523 573 DEBUGMSG((MODNAME_STR, "\n"));
524 574 }
525 575
526 576 if ((data = problem_lookup_uuid_next(uuid)) == NULL) {
527 577 DEBUGMSGTL((MODNAME_STR, "nextpr: next match not found for "
528 578 "%s; trying next column\n", uuid));
529 579 if (table_info->colnum >=
530 580 netsnmp_find_table_registration_info(reginfo)->max_column) {
531 581 snmp_free_varbind(table_info->indexes);
532 582 table_info->indexes = NULL;
533 583 table_info->number_indexes = 0;
534 584 DEBUGMSGTL((MODNAME_STR, "nextpr: out of columns\n"));
535 585 return (NULL);
536 586 }
537 587 table_info->colnum++;
538 588 DEBUGMSGTL((MODNAME_STR, "nextpr: search for col %u empty "
539 589 "uuid\n", table_info->colnum));
540 590
541 591 if ((data = problem_lookup_uuid_next("")) == NULL) {
542 592 DEBUGMSGTL((MODNAME_STR, "nextpr: next match not found "
543 593 "for empty uuid; stopping\n"));
544 594 snmp_free_varbind(table_info->indexes);
545 595 table_info->indexes = NULL;
546 596 table_info->number_indexes = 0;
547 597 return (NULL);
548 598 }
549 599 }
550 600
551 601 (void) snmp_set_var_typed_value(table_info->indexes, ASN_OCTET_STR,
552 602 (uchar_t *)data->d_aci_uuid, strlen(data->d_aci_uuid));
553 603 table_info->number_indexes = 1;
554 604
555 605 DEBUGMSGTL((MODNAME_STR, "matching data is %s@%p\n", data->d_aci_uuid,
556 606 data));
557 607
558 608 return (data);
559 609 }
560 610
561 611 /*
562 612 * Returns the problem data corresponding to the request in table_info.
563 613 * All request parameters are unmodified.
564 614 */
565 615 /*ARGSUSED*/
566 616 static sunFmProblem_data_t *
567 617 sunFmProblemTable_pr(netsnmp_handler_registration *reginfo,
568 618 netsnmp_table_request_info *table_info)
569 619 {
570 620 char *uuid;
571 621
572 622 ASSERT(table_info->number_indexes >= 1);
573 623
574 624 uuid = alloca(table_info->indexes->val_len + 1);
575 625 (void) strlcpy(uuid, (const char *)table_info->indexes->val.string,
576 626 table_info->indexes->val_len + 1);
577 627
578 628 return (problem_lookup_uuid_exact(uuid));
579 629 }
580 630
581 631 /*
582 632 * Returns the ASN.1 lexicographically first fault event after the one
583 633 * identified by table_info. Indexes are updated to reflect the OID
584 634 * of the data returned. This allows us to implement GETNEXT.
585 635 */
586 636 static sunFmFaultEvent_data_t *
587 637 sunFmFaultEventTable_nextfe(netsnmp_handler_registration *reginfo,
588 638 netsnmp_table_request_info *table_info, sunFmFaultStatus_data_t *statusp)
589 639 {
590 640 sunFmProblem_data_t *data;
591 641 sunFmFaultEvent_data_t *rv;
592 642 netsnmp_variable_list *var;
593 643 ulong_t index;
594 644
595 645 for (;;) {
596 646 switch (table_info->number_indexes) {
597 647 case 2:
598 648 default:
599 649 DEBUGMSGTL((MODNAME_STR, "nextfe: 2 indices:\n"));
600 650 DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
601 651 DEBUGMSG((MODNAME_STR, "\n"));
602 652 DEBUGMSGVAR((MODNAME_STR,
603 653 table_info->indexes->next_variable));
604 654 DEBUGMSG((MODNAME_STR, "\n"));
605 655 index = *(ulong_t *)
606 656 table_info->indexes->next_variable->val.integer + 1;
607 657
608 658 if ((data = sunFmProblemTable_pr(reginfo,
609 659 table_info)) != NULL &&
610 660 (*statusp = faultstatus_lookup_index_exact(data,
611 661 index)) != 0 &&
612 662 (rv = faultevent_lookup_index_exact(data, index)) !=
613 663 NULL) {
614 664 (void) snmp_set_var_typed_value(
615 665 table_info->indexes->next_variable,
616 666 ASN_UNSIGNED, (uchar_t *)&index,
617 667 sizeof (index));
618 668 return (rv);
619 669 }
620 670
621 671 if (sunFmProblemTable_nextpr(reginfo, table_info) ==
622 672 NULL)
623 673 return (NULL);
624 674 break;
625 675 case 1:
626 676 if ((data = sunFmProblemTable_pr(reginfo,
627 677 table_info)) != NULL) {
628 678 oid tmpoid[MAX_OID_LEN];
629 679 index = 0;
630 680
631 681 DEBUGMSGTL((MODNAME_STR, "nextfe: 1 index:\n"));
632 682 DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
633 683 DEBUGMSG((MODNAME_STR, "\n"));
634 684 var =
635 685 SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
636 686 (void) snmp_set_var_typed_value(var,
637 687 ASN_UNSIGNED, (uchar_t *)&index,
638 688 sizeof (index));
639 689 (void) memcpy(tmpoid, reginfo->rootoid,
640 690 reginfo->rootoid_len * sizeof (oid));
641 691 tmpoid[reginfo->rootoid_len] = 1;
|
↓ open down ↓ |
127 lines elided |
↑ open up ↑ |
642 692 tmpoid[reginfo->rootoid_len + 1] =
643 693 table_info->colnum;
644 694 if (build_oid_segment(var) != SNMPERR_SUCCESS) {
645 695 snmp_free_varbind(var);
646 696 return (NULL);
647 697 }
648 698 snmp_free_varbind(
649 699 table_info->indexes->next_variable);
650 700 table_info->indexes->next_variable = var;
651 701 table_info->number_indexes = 2;
652 - DEBUGMSGTL((MODNAME_STR, "nextfe: built fake "
653 - "index:\n"));
702 + DEBUGMSGTL((MODNAME_STR,
703 + "nextfe: built fake index: "));
654 704 DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
655 705 DEBUGMSG((MODNAME_STR, "\n"));
656 706 DEBUGMSGVAR((MODNAME_STR,
657 707 table_info->indexes->next_variable));
658 708 DEBUGMSG((MODNAME_STR, "\n"));
659 709 } else {
660 710 if (sunFmProblemTable_nextpr(reginfo,
661 711 table_info) == NULL)
662 712 return (NULL);
663 713 }
664 714 break;
665 715 case 0:
666 716 if (sunFmProblemTable_nextpr(reginfo, table_info) ==
667 717 NULL)
668 718 return (NULL);
669 719 break;
670 720 }
671 721 }
672 722 }
673 723
674 724 static sunFmFaultEvent_data_t *
675 725 sunFmFaultEventTable_fe(netsnmp_handler_registration *reginfo,
676 726 netsnmp_table_request_info *table_info, sunFmFaultStatus_data_t *statusp)
677 727 {
678 728 sunFmProblem_data_t *data;
679 729
680 730 ASSERT(table_info->number_indexes == 2);
681 731
682 732 if ((data = sunFmProblemTable_pr(reginfo, table_info)) == NULL)
683 733 return (NULL);
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
684 734
685 735 *statusp = faultstatus_lookup_index_exact(data,
686 736 *(ulong_t *)table_info->indexes->next_variable->val.integer);
687 737 if (*statusp == 0)
688 738 return (NULL);
689 739 return (faultevent_lookup_index_exact(data,
690 740 *(ulong_t *)table_info->indexes->next_variable->val.integer));
691 741 }
692 742
693 743 /*ARGSUSED*/
694 -static void
695 -sunFmProblemTable_return(unsigned int reg, void *arg)
744 +static int
745 +sunFmProblemTable_handler(netsnmp_mib_handler *handler,
746 + netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
747 + netsnmp_request_info *request)
696 748 {
697 - netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *)arg;
698 - netsnmp_request_info *request;
699 - netsnmp_agent_request_info *reqinfo;
700 - netsnmp_handler_registration *reginfo;
701 749 netsnmp_table_request_info *table_info;
702 750 sunFmProblem_data_t *data;
751 + int ret = SNMP_ERR_NOERROR;
703 752
704 - ASSERT(netsnmp_handler_check_cache(cache) != NULL);
753 + /*
754 + * We don't support MODE_GETBULK directly, so all bulk requests should
755 + * come through bulk_to_next helper. Make sure it stays that way.
756 + */
757 + ASSERT(reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT);
705 758
706 759 (void) pthread_mutex_lock(&update_lock);
707 - if (update_status != US_QUIET) {
708 - struct timeval tv;
709 760
710 - tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
711 - tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
761 + for (; request != NULL; request = request->next) {
762 + table_info = netsnmp_extract_table_info(request);
763 + if (table_info == NULL)
764 + continue;
712 765
713 - (void) snmp_alarm_register_hr(tv, 0, sunFmProblemTable_return,
714 - cache);
715 - (void) pthread_mutex_unlock(&update_lock);
716 - return;
717 - }
766 + /*
767 + * table_info->colnum contains the column number requested.
768 + * table_info->indexes contains a linked list of snmp variable
769 + * bindings for the indexes of the table. Values in the list
770 + * have been set corresponding to the indexes of the
771 + * request. We have other guarantees as well:
772 + *
773 + * - The column number is always within range.
774 + * - If we have no index data, table_info->index_oid_len is 0.
775 + * - We will never receive requests outside our table nor
776 + * those with the first subid anything other than 1 (Entry)
777 + * nor those without a column number. This is true even
778 + * for GETNEXT requests.
779 + */
780 + switch (reqinfo->mode) {
781 + case MODE_GET:
782 + data = sunFmProblemTable_pr(reginfo, table_info);
783 + if (data == NULL)
784 + goto out;
785 + break;
786 + case MODE_GETNEXT:
787 + data = sunFmProblemTable_nextpr(reginfo, table_info);
788 + if (data == NULL)
789 + goto out;
790 + break;
791 + default:
792 + (void) snmp_log(LOG_ERR, MODNAME_STR
793 + ": unsupported request mode: %d\n", reqinfo->mode);
794 + ret = SNMP_ERR_GENERR;
795 + goto out;
796 + }
718 797
719 - request = cache->requests;
720 - reqinfo = cache->reqinfo;
721 - reginfo = cache->reginfo;
798 + switch (table_info->colnum) {
799 + case SUNFMPROBLEM_COL_UUID:
800 + (void) netsnmp_table_build_result(reginfo, request,
801 + table_info, ASN_OCTET_STR,
802 + (uchar_t *)data->d_aci_uuid,
803 + strlen(data->d_aci_uuid));
804 + break;
805 + case SUNFMPROBLEM_COL_HOSTNAME: {
806 + char hostname[MAXHOSTNAMELEN+1];
722 807
723 - table_info = netsnmp_extract_table_info(request);
724 - request->delegated = 0;
808 + (void) gethostname(hostname, sizeof (hostname) - 1);
809 + (void) netsnmp_table_build_result(reginfo, request,
810 + table_info, ASN_OCTET_STR, (uchar_t *)hostname,
811 + strlen(hostname));
812 + break;
813 + }
814 + case SUNFMPROBLEM_COL_CODE:
815 + (void) netsnmp_table_build_result(reginfo, request,
816 + table_info, ASN_OCTET_STR,
817 + (uchar_t *)data->d_aci_code,
818 + strlen(data->d_aci_code));
819 + break;
820 + case SUNFMPROBLEM_COL_TYPE:
821 + (void) netsnmp_table_build_result(reginfo, request,
822 + table_info, ASN_OCTET_STR,
823 + (uchar_t *)data->d_aci_type,
824 + strlen(data->d_aci_type));
825 + break;
826 + case SUNFMPROBLEM_COL_SEVERITY:
827 + (void) netsnmp_table_build_result(reginfo, request,
828 + table_info, ASN_OCTET_STR,
829 + (uchar_t *)data->d_aci_severity,
830 + strlen(data->d_aci_severity));
831 + break;
832 + case SUNFMPROBLEM_COL_URL:
833 + (void) netsnmp_table_build_result(reginfo, request,
834 + table_info, ASN_OCTET_STR,
835 + (uchar_t *)data->d_aci_url,
836 + strlen(data->d_aci_url));
837 + break;
838 + case SUNFMPROBLEM_COL_DESC:
839 + (void) netsnmp_table_build_result(reginfo, request,
840 + table_info, ASN_OCTET_STR,
841 + (uchar_t *)data->d_aci_desc,
842 + strlen(data->d_aci_desc));
843 + break;
844 + case SUNFMPROBLEM_COL_FMRI:
845 + (void) netsnmp_table_build_result(reginfo, request,
846 + table_info, ASN_OCTET_STR,
847 + (uchar_t *)data->d_aci_fmri,
848 + strlen(data->d_aci_fmri));
849 + break;
850 + case SUNFMPROBLEM_COL_DIAGENGINE:
851 + (void) netsnmp_table_build_result(reginfo, request,
852 + table_info, ASN_OCTET_STR,
853 + (uchar_t *)data->d_diag_engine,
854 + strlen(data->d_diag_engine));
855 + break;
856 + case SUNFMPROBLEM_COL_DIAGTIME: {
857 + /*
858 + * The date_n_time function is not Y2038-safe; this may
859 + * need to be updated when a suitable Y2038-safe
860 + * Net-SNMP API is available.
861 + */
862 + size_t dt_size;
863 + time_t dt_time = (time_t)data->d_diag_time.tv_sec;
864 + uchar_t *dt = date_n_time(&dt_time, &dt_size);
725 865
726 - ASSERT(table_info->colnum >= SUNFMPROBLEM_COLMIN);
727 - ASSERT(table_info->colnum <= SUNFMPROBLEM_COLMAX);
728 -
729 - /*
730 - * table_info->colnum contains the column number requested.
731 - * table_info->indexes contains a linked list of snmp variable
732 - * bindings for the indexes of the table. Values in the list
733 - * have been set corresponding to the indexes of the
734 - * request. We have other guarantees as well:
735 - *
736 - * - The column number is always within range.
737 - * - If we have no index data, table_info->index_oid_len is 0.
738 - * - We will never receive requests outside our table nor
739 - * those with the first subid anything other than 1 (Entry)
740 - * nor those without a column number. This is true even
741 - * for GETNEXT requests.
742 - */
743 -
744 - switch (reqinfo->mode) {
745 - case MODE_GET:
746 - if ((data = sunFmProblemTable_pr(reginfo, table_info)) ==
747 - NULL) {
748 - netsnmp_free_delegated_cache(cache);
749 - (void) pthread_mutex_unlock(&update_lock);
750 - return;
866 + (void) netsnmp_table_build_result(reginfo, request,
867 + table_info, ASN_OCTET_STR, dt, dt_size);
868 + break;
751 869 }
752 - break;
753 - case MODE_GETNEXT:
754 - case MODE_GETBULK:
755 - if ((data = sunFmProblemTable_nextpr(reginfo, table_info)) ==
756 - NULL) {
757 - netsnmp_free_delegated_cache(cache);
758 - (void) pthread_mutex_unlock(&update_lock);
759 - return;
870 + case SUNFMPROBLEM_COL_SUSPECTCOUNT:
871 + (void) netsnmp_table_build_result(reginfo, request,
872 + table_info, ASN_UNSIGNED,
873 + (uchar_t *)&data->d_nsuspects,
874 + sizeof (data->d_nsuspects));
875 + break;
876 + default:
877 + (void) netsnmp_table_build_result(reginfo, request,
878 + table_info, ASN_OCTET_STR, (uchar_t *)"-",
879 + strlen("-"));
880 + break;
760 881 }
761 - break;
762 - default:
763 - (void) snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request "
764 - "mode %d\n", reqinfo->mode);
765 - netsnmp_free_delegated_cache(cache);
766 - (void) pthread_mutex_unlock(&update_lock);
767 - return;
768 882 }
769 883
770 - switch (table_info->colnum) {
771 - case SUNFMPROBLEM_COL_UUID:
772 - {
773 - (void) netsnmp_table_build_result(reginfo, request, table_info,
774 - ASN_OCTET_STR, (uchar_t *)data->d_aci_uuid,
775 - strlen(data->d_aci_uuid));
776 - break;
777 - }
778 - case SUNFMPROBLEM_COL_CODE:
779 - {
780 - (void) netsnmp_table_build_result(reginfo, request, table_info,
781 - ASN_OCTET_STR, (uchar_t *)data->d_aci_code,
782 - strlen(data->d_aci_code));
783 - break;
784 - }
785 - case SUNFMPROBLEM_COL_URL:
786 - {
787 - (void) netsnmp_table_build_result(reginfo, request, table_info,
788 - ASN_OCTET_STR, (uchar_t *)data->d_aci_url,
789 - strlen(data->d_aci_url));
790 - break;
791 - }
792 - case SUNFMPROBLEM_COL_DIAGENGINE:
793 - {
794 - (void) netsnmp_table_build_result(reginfo, request, table_info,
795 - ASN_OCTET_STR, (uchar_t *)data->d_diag_engine,
796 - strlen(data->d_diag_engine));
797 - break;
798 - }
799 - case SUNFMPROBLEM_COL_DIAGTIME:
800 - {
801 - /*
802 - * The date_n_time function is not Y2038-safe; this may
803 - * need to be updated when a suitable Y2038-safe Net-SNMP
804 - * API is available.
805 - */
806 - size_t dt_size;
807 - time_t dt_time = (time_t)data->d_diag_time.tv_sec;
808 - uchar_t *dt = date_n_time(&dt_time, &dt_size);
809 -
810 - (void) netsnmp_table_build_result(reginfo, request, table_info,
811 - ASN_OCTET_STR, dt, dt_size);
812 - break;
813 - }
814 - case SUNFMPROBLEM_COL_SUSPECTCOUNT:
815 - {
816 - (void) netsnmp_table_build_result(reginfo, request, table_info,
817 - ASN_UNSIGNED, (uchar_t *)&data->d_nsuspects,
818 - sizeof (data->d_nsuspects));
819 - break;
820 - }
821 - default:
822 - break;
823 - }
824 -
825 - netsnmp_free_delegated_cache(cache);
884 +out:
826 885 (void) pthread_mutex_unlock(&update_lock);
886 + return (ret);
827 887 }
828 888
889 +/*ARGSUSED*/
829 890 static int
830 -sunFmProblemTable_handler(netsnmp_mib_handler *handler,
891 +sunFmFaultEventTable_handler(netsnmp_mib_handler *handler,
831 892 netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
832 - netsnmp_request_info *requests)
893 + netsnmp_request_info *request)
833 894 {
834 - netsnmp_request_info *request;
835 - struct timeval tv;
836 -
837 - tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
838 - tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
839 -
840 - request_update();
841 -
842 - for (request = requests; request; request = request->next) {
843 - if (request->processed != 0)
844 - continue;
845 -
846 - if (netsnmp_extract_table_info(request) == NULL)
847 - continue;
848 -
849 - request->delegated = 1;
850 - (void) snmp_alarm_register_hr(tv, 0,
851 - sunFmProblemTable_return,
852 - (void *) netsnmp_create_delegated_cache(handler, reginfo,
853 - reqinfo, request, NULL));
854 - }
855 -
856 - return (SNMP_ERR_NOERROR);
857 -}
858 -
859 -/*ARGSUSED*/
860 -static void
861 -sunFmFaultEventTable_return(unsigned int reg, void *arg)
862 -{
863 - netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *)arg;
864 - netsnmp_request_info *request;
865 - netsnmp_agent_request_info *reqinfo;
866 - netsnmp_handler_registration *reginfo;
867 895 netsnmp_table_request_info *table_info;
868 - sunFmProblem_data_t *pdata;
869 896 sunFmFaultEvent_data_t *data;
870 897 sunFmFaultStatus_data_t status;
898 + sunFmProblem_data_t *pdata;
899 + int ret = SNMP_ERR_NOERROR;
871 900
872 - ASSERT(netsnmp_handler_check_cache(cache) != NULL);
901 + /*
902 + * We don't support MODE_GETBULK directly, so all bulk requests should
903 + * come through bulk_to_next helper. Make sure it stays that way.
904 + */
905 + ASSERT(reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT);
873 906
874 907 (void) pthread_mutex_lock(&update_lock);
875 - if (update_status != US_QUIET) {
876 - struct timeval tv;
877 908
878 - tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
879 - tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
909 + for (; request != NULL; request = request->next) {
910 + table_info = netsnmp_extract_table_info(request);
911 + if (table_info == NULL)
912 + continue;
880 913
881 - (void) snmp_alarm_register_hr(tv, 0,
882 - sunFmFaultEventTable_return, cache);
883 - (void) pthread_mutex_unlock(&update_lock);
884 - return;
885 - }
914 + ASSERT(table_info->colnum >= SUNFMFAULTEVENT_COLMIN);
915 + ASSERT(table_info->colnum <= SUNFMFAULTEVENT_COLMAX);
886 916
887 - request = cache->requests;
888 - reqinfo = cache->reqinfo;
889 - reginfo = cache->reginfo;
917 + /*
918 + * table_info->colnum contains the column number requested.
919 + * table_info->indexes contains a linked list of snmp variable
920 + * bindings for the indexes of the table. Values in the list
921 + * have been set corresponding to the indexes of the
922 + * request. We have other guarantees as well:
923 + *
924 + * - The column number is always within range.
925 + * - If we have no index data, table_info->index_oid_len is 0.
926 + * - We will never receive requests outside our table nor
927 + * those with the first subid anything other than 1 (Entry)
928 + * nor those without a column number. This is true even
929 + * for GETNEXT requests.
930 + */
931 + switch (reqinfo->mode) {
932 + case MODE_GET:
933 + data = sunFmFaultEventTable_fe(reginfo, table_info,
934 + &status);
935 + if (data == NULL)
936 + goto out;
937 + break;
938 + case MODE_GETNEXT:
939 + data = sunFmFaultEventTable_nextfe(reginfo, table_info,
940 + &status);
941 + if (data == NULL)
942 + goto out;
943 + break;
944 + default:
945 + (void) snmp_log(LOG_ERR, MODNAME_STR
946 + ": unsupported request mode: %d\n", reqinfo->mode);
947 + ret = SNMP_ERR_GENERR;
948 + goto out;
949 + }
890 950
891 - table_info = netsnmp_extract_table_info(request);
892 - request->delegated = 0;
951 + switch (table_info->colnum) {
952 + case SUNFMFAULTEVENT_COL_PROBLEMUUID:
953 + if ((pdata = sunFmProblemTable_pr(reginfo, table_info))
954 + == NULL) {
955 + (void) netsnmp_table_build_result(reginfo,
956 + request, table_info, ASN_OCTET_STR,
957 + NULL, 0);
958 + break;
959 + }
960 + (void) netsnmp_table_build_result(reginfo, request,
961 + table_info, ASN_OCTET_STR,
962 + (uchar_t *)pdata->d_aci_uuid,
963 + strlen(pdata->d_aci_uuid));
964 + break;
965 + case SUNFMFAULTEVENT_COL_CLASS: {
966 + char *class = "-";
893 967
894 - ASSERT(table_info->colnum >= SUNFMFAULTEVENT_COLMIN);
895 - ASSERT(table_info->colnum <= SUNFMFAULTEVENT_COLMAX);
896 -
897 - /*
898 - * table_info->colnum contains the column number requested.
899 - * table_info->indexes contains a linked list of snmp variable
900 - * bindings for the indexes of the table. Values in the list
901 - * have been set corresponding to the indexes of the
902 - * request. We have other guarantees as well:
903 - *
904 - * - The column number is always within range.
905 - * - If we have no index data, table_info->index_oid_len is 0.
906 - * - We will never receive requests outside our table nor
907 - * those with the first subid anything other than 1 (Entry)
908 - * nor those without a column number. This is true even
909 - * for GETNEXT requests.
910 - */
911 -
912 - switch (reqinfo->mode) {
913 - case MODE_GET:
914 - if ((data = sunFmFaultEventTable_fe(reginfo, table_info,
915 - &status)) == NULL) {
916 - netsnmp_free_delegated_cache(cache);
917 - (void) pthread_mutex_unlock(&update_lock);
918 - return;
968 + (void) nvlist_lookup_string(data, FM_CLASS, &class);
969 + (void) netsnmp_table_build_result(reginfo, request,
970 + table_info, ASN_OCTET_STR, (uchar_t *)class,
971 + strlen(class));
972 + break;
919 973 }
920 - break;
921 - case MODE_GETNEXT:
922 - case MODE_GETBULK:
923 - if ((data = sunFmFaultEventTable_nextfe(reginfo, table_info,
924 - &status)) == NULL) {
925 - netsnmp_free_delegated_cache(cache);
926 - (void) pthread_mutex_unlock(&update_lock);
927 - return;
928 - }
929 - break;
930 - default:
931 - (void) snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request "
932 - "mode %d\n", reqinfo->mode);
933 - netsnmp_free_delegated_cache(cache);
934 - (void) pthread_mutex_unlock(&update_lock);
935 - return;
936 - }
974 + case SUNFMFAULTEVENT_COL_CERTAINTY: {
975 + uint8_t pct = 0;
976 + ulong_t pl;
937 977
938 - switch (table_info->colnum) {
939 - case SUNFMFAULTEVENT_COL_PROBLEMUUID:
940 - {
941 - if ((pdata = sunFmProblemTable_pr(reginfo, table_info))
942 - == NULL) {
978 + (void) nvlist_lookup_uint8(data, FM_FAULT_CERTAINTY,
979 + &pct);
980 + pl = (ulong_t)pct;
943 981 (void) netsnmp_table_build_result(reginfo, request,
944 - table_info, ASN_OCTET_STR, NULL, 0);
982 + table_info, ASN_UNSIGNED, (uchar_t *)&pl,
983 + sizeof (pl));
945 984 break;
946 985 }
947 - (void) netsnmp_table_build_result(reginfo, request, table_info,
948 - ASN_OCTET_STR, (uchar_t *)pdata->d_aci_uuid,
949 - strlen(pdata->d_aci_uuid));
950 - break;
951 - }
952 - case SUNFMFAULTEVENT_COL_CLASS:
953 - {
954 - char *class = "-";
986 + case SUNFMFAULTEVENT_COL_ASRU: {
987 + nvlist_t *asru = NULL;
988 + char *fmri = "-", *str;
955 989
956 - (void) nvlist_lookup_string(data, FM_CLASS, &class);
957 - (void) netsnmp_table_build_result(reginfo, request, table_info,
958 - ASN_OCTET_STR, (uchar_t *)class, strlen(class));
959 - break;
960 - }
961 - case SUNFMFAULTEVENT_COL_CERTAINTY:
962 - {
963 - uint8_t pct = 0;
964 - ulong_t pl;
990 + (void) nvlist_lookup_nvlist(data, FM_FAULT_ASRU, &asru);
991 + if ((str = nvl2fmri(asru)) != NULL)
992 + fmri = str;
965 993
966 - (void) nvlist_lookup_uint8(data, FM_FAULT_CERTAINTY,
967 - &pct);
968 - pl = (ulong_t)pct;
969 - (void) netsnmp_table_build_result(reginfo, request, table_info,
970 - ASN_UNSIGNED, (uchar_t *)&pl, sizeof (pl));
971 - break;
972 - }
973 - case SUNFMFAULTEVENT_COL_ASRU:
974 - {
975 - nvlist_t *asru = NULL;
976 - char *fmri, *str;
994 + (void) netsnmp_table_build_result(reginfo, request,
995 + table_info, ASN_OCTET_STR, (uchar_t *)fmri,
996 + strlen(fmri));
997 + free(str);
998 + break;
999 + }
1000 + case SUNFMFAULTEVENT_COL_FRU: {
1001 + nvlist_t *fru = NULL;
1002 + char *fmri = "-", *str;
977 1003
978 - (void) nvlist_lookup_nvlist(data, FM_FAULT_ASRU, &asru);
979 - if ((str = sunFm_nvl2str(asru)) == NULL)
980 - fmri = "-";
981 - else
982 - fmri = str;
1004 + (void) nvlist_lookup_nvlist(data, FM_FAULT_FRU, &fru);
1005 + if ((str = nvl2fmri(fru)) != NULL)
1006 + fmri = str;
983 1007
984 - (void) netsnmp_table_build_result(reginfo, request, table_info,
985 - ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri));
986 - free(str);
987 - break;
988 - }
989 - case SUNFMFAULTEVENT_COL_FRU:
990 - {
991 - nvlist_t *fru = NULL;
992 - char *fmri, *str;
1008 + (void) netsnmp_table_build_result(reginfo, request,
1009 + table_info, ASN_OCTET_STR, (uchar_t *)fmri,
1010 + strlen(fmri));
1011 + free(str);
1012 + break;
1013 + }
1014 + case SUNFMFAULTEVENT_COL_RESOURCE: {
1015 + nvlist_t *rsrc = NULL;
1016 + char *fmri = "-", *str;
993 1017
994 - (void) nvlist_lookup_nvlist(data, FM_FAULT_FRU, &fru);
995 - if ((str = sunFm_nvl2str(fru)) == NULL)
996 - fmri = "-";
997 - else
998 - fmri = str;
1018 + (void) nvlist_lookup_nvlist(data, FM_FAULT_RESOURCE,
1019 + &rsrc);
1020 + if ((str = nvl2fmri(rsrc)) != NULL)
1021 + fmri = str;
999 1022
1000 - (void) netsnmp_table_build_result(reginfo, request, table_info,
1001 - ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri));
1002 - free(str);
1003 - break;
1004 - }
1005 - case SUNFMFAULTEVENT_COL_RESOURCE:
1006 - {
1007 - nvlist_t *rsrc = NULL;
1008 - char *fmri, *str;
1023 + (void) netsnmp_table_build_result(reginfo, request,
1024 + table_info, ASN_OCTET_STR, (uchar_t *)fmri,
1025 + strlen(fmri));
1026 + free(str);
1027 + break;
1028 + }
1029 + case SUNFMFAULTEVENT_COL_STATUS: {
1030 + ulong_t pl = SUNFMFAULTEVENT_STATE_OTHER;
1009 1031
1010 - (void) nvlist_lookup_nvlist(data, FM_FAULT_RESOURCE, &rsrc);
1011 - if ((str = sunFm_nvl2str(rsrc)) == NULL)
1012 - fmri = "-";
1013 - else
1014 - fmri = str;
1032 + if (status & FM_SUSPECT_FAULTY)
1033 + pl = SUNFMFAULTEVENT_STATE_FAULTY;
1034 + else if (status & FM_SUSPECT_NOT_PRESENT)
1035 + pl = SUNFMFAULTEVENT_STATE_REMOVED;
1036 + else if (status & FM_SUSPECT_REPLACED)
1037 + pl = SUNFMFAULTEVENT_STATE_REPLACED;
1038 + else if (status & FM_SUSPECT_REPAIRED)
1039 + pl = SUNFMFAULTEVENT_STATE_REPAIRED;
1040 + else if (status & FM_SUSPECT_ACQUITTED)
1041 + pl = SUNFMFAULTEVENT_STATE_ACQUITTED;
1042 + (void) netsnmp_table_build_result(reginfo, request,
1043 + table_info, ASN_INTEGER, (uchar_t *)&pl,
1044 + sizeof (pl));
1045 + break;
1046 + }
1047 + case SUNFMFAULTEVENT_COL_LOCATION: {
1048 + char *location = "-";
1015 1049
1016 - (void) netsnmp_table_build_result(reginfo, request, table_info,
1017 - ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri));
1018 - free(str);
1019 - break;
1050 + (void) nvlist_lookup_string(data, FM_FAULT_LOCATION,
1051 + &location);
1052 + (void) netsnmp_table_build_result(reginfo, request,
1053 + table_info, ASN_OCTET_STR, (uchar_t *)location,
1054 + strlen(location));
1055 + break;
1056 + }
1057 + default:
1058 + break;
1059 + }
1020 1060 }
1021 - case SUNFMFAULTEVENT_COL_STATUS:
1022 - {
1023 - ulong_t pl = SUNFMFAULTEVENT_STATE_OTHER;
1024 1061
1025 - if (status & FM_SUSPECT_FAULTY)
1026 - pl = SUNFMFAULTEVENT_STATE_FAULTY;
1027 - else if (status & FM_SUSPECT_NOT_PRESENT)
1028 - pl = SUNFMFAULTEVENT_STATE_REMOVED;
1029 - else if (status & FM_SUSPECT_REPLACED)
1030 - pl = SUNFMFAULTEVENT_STATE_REPLACED;
1031 - else if (status & FM_SUSPECT_REPAIRED)
1032 - pl = SUNFMFAULTEVENT_STATE_REPAIRED;
1033 - else if (status & FM_SUSPECT_ACQUITTED)
1034 - pl = SUNFMFAULTEVENT_STATE_ACQUITTED;
1035 - (void) netsnmp_table_build_result(reginfo, request, table_info,
1036 - ASN_INTEGER, (uchar_t *)&pl, sizeof (pl));
1037 - break;
1038 - }
1039 - case SUNFMFAULTEVENT_COL_LOCATION:
1040 - {
1041 - char *location = "-";
1042 -
1043 - (void) nvlist_lookup_string(data, FM_FAULT_LOCATION, &location);
1044 - (void) netsnmp_table_build_result(reginfo, request, table_info,
1045 - ASN_OCTET_STR, (uchar_t *)location, strlen(location));
1046 - break;
1047 - }
1048 - default:
1049 - break;
1050 - }
1051 -
1052 - netsnmp_free_delegated_cache(cache);
1062 +out:
1053 1063 (void) pthread_mutex_unlock(&update_lock);
1054 -}
1055 -
1056 -static int
1057 -sunFmFaultEventTable_handler(netsnmp_mib_handler *handler,
1058 - netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
1059 - netsnmp_request_info *requests)
1060 -{
1061 - netsnmp_request_info *request;
1062 - struct timeval tv;
1063 -
1064 - tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
1065 - tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
1066 -
1067 - request_update();
1068 -
1069 - for (request = requests; request; request = request->next) {
1070 - if (request->processed != 0)
1071 - continue;
1072 -
1073 - if (netsnmp_extract_table_info(request) == NULL)
1074 - continue;
1075 -
1076 - request->delegated = 1;
1077 - (void) snmp_alarm_register_hr(tv, 0,
1078 - sunFmFaultEventTable_return,
1079 - (void *) netsnmp_create_delegated_cache(handler, reginfo,
1080 - reqinfo, request, NULL));
1081 - }
1082 -
1083 - return (SNMP_ERR_NOERROR);
1064 + return (ret);
1084 1065 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX