8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / fm / libfmd_snmp / common / scheme.c
blob55c45a7ae3dc7caf55e9c261f7b991c97cb02d0d
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/fm/protocol.h>
30 #include <sys/types.h>
31 #include <sys/systeminfo.h>
32 #include <fm/fmd_snmp.h>
33 #include <fm/libtopo.h>
34 #include <net-snmp/net-snmp-config.h>
35 #include <net-snmp/net-snmp-includes.h>
36 #include <net-snmp/agent/net-snmp-agent-includes.h>
37 #include <libnvpair.h>
38 #include <limits.h>
39 #include <strings.h>
40 #include <stddef.h>
41 #include <unistd.h>
42 #include <dlfcn.h>
43 #include <errno.h>
45 #define SCHEMEDIR_BASE "/usr/lib/fm/fmd/schemes"
47 #if defined(__sparcv9)
48 #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/sparcv9"
49 #elif defined(__amd64)
50 #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/amd64"
51 #else
52 #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE
53 #endif
55 typedef struct fmd_scheme_ops {
56 int (*sop_init)(void);
57 void (*sop_fini)(void);
58 ssize_t (*sop_nvl2str)(nvlist_t *, char *, size_t);
59 } fmd_scheme_ops_t;
61 typedef struct fmd_scheme_opd {
62 const char *opd_name; /* symbol name of scheme function */
63 size_t opd_off; /* offset within fmd_scheme_ops_t */
64 } fmd_scheme_opd_t;
66 typedef struct fmd_scheme {
67 struct fmd_scheme *sch_next; /* next scheme on list of schemes */
68 char *sch_name; /* name of this scheme (fmri prefix) */
69 void *sch_dlp; /* libdl(3DL) shared library handle */
70 int sch_err; /* if negative entry, errno to return */
71 fmd_scheme_ops_t sch_ops; /* scheme function pointers */
72 } fmd_scheme_t;
74 static fmd_scheme_t *sch_list; /* list of cached schemes */
75 static char *g_root; /* fmd root dir */
76 static struct topo_hdl *g_thp;
78 static long
79 fmd_scheme_notsup(void)
81 errno = ENOTSUP;
82 return (-1);
85 static int
86 fmd_scheme_nop(void)
88 return (0);
92 * Default values for the scheme ops. If a scheme function is not defined in
93 * the module, then this operation is implemented using the default function.
95 static const fmd_scheme_ops_t _fmd_scheme_default_ops = {
96 (int (*)())fmd_scheme_nop, /* sop_init */
97 (void (*)())fmd_scheme_nop, /* sop_fini */
98 (ssize_t (*)())fmd_scheme_notsup, /* sop_nvl2str */
102 * Scheme ops descriptions. These names and offsets are used by the function
103 * fmd_scheme_rtld_init(), defined below, to load up a fmd_scheme_ops_t.
105 static const fmd_scheme_opd_t _fmd_scheme_ops[] = {
106 { "fmd_fmri_init", offsetof(fmd_scheme_ops_t, sop_init) },
107 { "fmd_fmri_fini", offsetof(fmd_scheme_ops_t, sop_fini) },
108 { "fmd_fmri_nvl2str", offsetof(fmd_scheme_ops_t, sop_nvl2str) },
109 { NULL, 0 }
112 static fmd_scheme_t *
113 fmd_scheme_create(const char *name)
115 fmd_scheme_t *sp;
117 if ((sp = malloc(sizeof (fmd_scheme_t))) == NULL ||
118 (sp->sch_name = strdup(name)) == NULL) {
119 free(sp);
120 return (NULL);
123 sp->sch_next = sch_list;
124 sp->sch_dlp = NULL;
125 sp->sch_err = 0;
126 sp->sch_ops = _fmd_scheme_default_ops;
128 sch_list = sp;
129 return (sp);
132 static int
133 fmd_scheme_rtld_init(fmd_scheme_t *sp)
135 const fmd_scheme_opd_t *opd;
136 void *p;
138 for (opd = _fmd_scheme_ops; opd->opd_name != NULL; opd++) {
139 if ((p = dlsym(sp->sch_dlp, opd->opd_name)) != NULL)
140 *(void **)((uintptr_t)&sp->sch_ops + opd->opd_off) = p;
143 return (sp->sch_ops.sop_init());
146 static fmd_scheme_t *
147 fmd_scheme_lookup(const char *dir, const char *name)
149 fmd_scheme_t *sp;
150 char path[PATH_MAX];
152 for (sp = sch_list; sp != NULL; sp = sp->sch_next) {
153 if (strcmp(name, sp->sch_name) == 0)
154 return (sp);
157 if ((sp = fmd_scheme_create(name)) == NULL)
158 return (NULL); /* errno is set for us */
160 (void) snprintf(path, sizeof (path), "%s%s/%s.so",
161 g_root ? g_root : "", dir, name);
163 if (access(path, F_OK) != 0) {
164 sp->sch_err = errno;
165 return (sp);
168 if ((sp->sch_dlp = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_PARENT)) ==
169 NULL) {
170 sp->sch_err = ELIBACC;
171 return (sp);
174 if (fmd_scheme_rtld_init(sp) != 0) {
175 sp->sch_err = errno;
176 (void) dlclose(sp->sch_dlp);
177 sp->sch_dlp = NULL;
180 return (sp);
183 char *
184 sunFm_nvl2str(nvlist_t *nvl)
186 fmd_scheme_t *sp;
187 char c, *name, *s = NULL;
188 ssize_t len;
190 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) {
191 DEBUGMSGTL((MODNAME_STR, "fmri does not contain required "
192 "'%s' nvpair\n", FM_FMRI_SCHEME));
193 return (NULL);
196 if ((sp = fmd_scheme_lookup(DEFAULTSCHEMEDIR, name)) == NULL ||
197 sp->sch_dlp == NULL || sp->sch_err != 0) {
198 const char *msg =
199 sp->sch_err == ELIBACC ? dlerror() : strerror(sp->sch_err);
200 DEBUGMSGTL((MODNAME_STR, "cannot init '%s' scheme library to "
201 "format fmri: %s\n", name, msg ? msg : "unknown error"));
202 return (NULL);
205 if ((len = sp->sch_ops.sop_nvl2str(nvl, &c, sizeof (c))) == -1 ||
206 (s = malloc(len + 1)) == NULL ||
207 sp->sch_ops.sop_nvl2str(nvl, s, len + 1) == -1) {
208 DEBUGMSGTL((MODNAME_STR, "cannot format fmri using scheme '%s'",
209 name));
210 free(s);
211 return (NULL);
214 return (s);
217 void *
218 fmd_fmri_alloc(size_t size)
220 return (malloc(size));
223 void *
224 fmd_fmri_zalloc(size_t size)
226 void *data;
228 if ((data = malloc(size)) != NULL)
229 bzero(data, size);
231 return (data);
234 /*ARGSUSED*/
235 void
236 fmd_fmri_free(void *data, size_t size)
238 free(data);
242 fmd_fmri_error(int err)
244 errno = err;
245 return (-1);
248 char *
249 fmd_fmri_strescape(const char *s)
251 return (strdup(s));
254 char *
255 fmd_fmri_strdup(const char *s)
257 return (strdup(s));
260 void
261 fmd_fmri_strfree(char *s)
263 free(s);
266 const char *
267 fmd_fmri_get_rootdir(void)
269 return (g_root ? g_root : "");
272 const char *
273 fmd_fmri_get_platform(void)
275 static char platform[MAXNAMELEN];
277 if (platform[0] == '\0')
278 (void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
280 return (platform);
283 uint64_t
284 fmd_fmri_get_drgen(void)
286 return (0);
290 fmd_fmri_set_errno(int err)
292 errno = err;
293 return (-1);
296 /*ARGSUSED*/
297 void
298 fmd_fmri_warn(const char *format, ...)
302 struct topo_hdl *
303 fmd_fmri_topo_hold(int version)
305 int err;
307 if (version != TOPO_VERSION)
308 return (NULL);
310 if (g_thp == NULL) {
311 if ((g_thp = topo_open(TOPO_VERSION, "/", &err)) == NULL) {
312 DEBUGMSGTL((MODNAME_STR, "topo_open failed: %s\n",
313 topo_strerror(err)));
314 return (NULL);
318 return (g_thp);
321 /*ARGSUSED*/
322 void
323 fmd_fmri_topo_rele(struct topo_hdl *thp)
325 /* nothing to do */