1749f21d3Swesolows /*
2749f21d3Swesolows * CDDL HEADER START
3749f21d3Swesolows *
4749f21d3Swesolows * The contents of this file are subject to the terms of the
5749f21d3Swesolows * Common Development and Distribution License (the "License").
6749f21d3Swesolows * You may not use this file except in compliance with the License.
7749f21d3Swesolows *
8749f21d3Swesolows * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9749f21d3Swesolows * or http://www.opensolaris.org/os/licensing.
10749f21d3Swesolows * See the License for the specific language governing permissions
11749f21d3Swesolows * and limitations under the License.
12749f21d3Swesolows *
13749f21d3Swesolows * When distributing Covered Code, include this CDDL HEADER in each
14749f21d3Swesolows * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15749f21d3Swesolows * If applicable, add the following below this CDDL HEADER, with the
16749f21d3Swesolows * fields enclosed by brackets "[]" replaced with your own identifying
17749f21d3Swesolows * information: Portions Copyright [yyyy] [name of copyright owner]
18749f21d3Swesolows *
19749f21d3Swesolows * CDDL HEADER END
20749f21d3Swesolows */
21749f21d3Swesolows
22749f21d3Swesolows /*
231fe76c0bSwesolows * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24749f21d3Swesolows * Use is subject to license terms.
25749f21d3Swesolows */
26749f21d3Swesolows
27749f21d3Swesolows #pragma ident "%Z%%M% %I% %E% SMI"
28749f21d3Swesolows
29749f21d3Swesolows #include <sys/fm/protocol.h>
30749f21d3Swesolows #include <sys/types.h>
31749f21d3Swesolows #include <sys/systeminfo.h>
32749f21d3Swesolows #include <fm/fmd_snmp.h>
331fe76c0bSwesolows #include <fm/libtopo.h>
34749f21d3Swesolows #include <net-snmp/net-snmp-config.h>
35749f21d3Swesolows #include <net-snmp/net-snmp-includes.h>
36749f21d3Swesolows #include <net-snmp/agent/net-snmp-agent-includes.h>
37749f21d3Swesolows #include <libnvpair.h>
38749f21d3Swesolows #include <limits.h>
39749f21d3Swesolows #include <strings.h>
40749f21d3Swesolows #include <stddef.h>
41749f21d3Swesolows #include <unistd.h>
42749f21d3Swesolows #include <dlfcn.h>
43749f21d3Swesolows #include <errno.h>
44749f21d3Swesolows
45749f21d3Swesolows #define SCHEMEDIR_BASE "/usr/lib/fm/fmd/schemes"
46749f21d3Swesolows
47749f21d3Swesolows #if defined(__sparcv9)
48749f21d3Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/sparcv9"
49749f21d3Swesolows #elif defined(__amd64)
50749f21d3Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/amd64"
51749f21d3Swesolows #else
52749f21d3Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE
53749f21d3Swesolows #endif
54749f21d3Swesolows
55749f21d3Swesolows typedef struct fmd_scheme_ops {
56749f21d3Swesolows int (*sop_init)(void);
57749f21d3Swesolows void (*sop_fini)(void);
58749f21d3Swesolows ssize_t (*sop_nvl2str)(nvlist_t *, char *, size_t);
59749f21d3Swesolows } fmd_scheme_ops_t;
60749f21d3Swesolows
61749f21d3Swesolows typedef struct fmd_scheme_opd {
62749f21d3Swesolows const char *opd_name; /* symbol name of scheme function */
63749f21d3Swesolows size_t opd_off; /* offset within fmd_scheme_ops_t */
64749f21d3Swesolows } fmd_scheme_opd_t;
65749f21d3Swesolows
66749f21d3Swesolows typedef struct fmd_scheme {
67749f21d3Swesolows struct fmd_scheme *sch_next; /* next scheme on list of schemes */
68749f21d3Swesolows char *sch_name; /* name of this scheme (fmri prefix) */
69749f21d3Swesolows void *sch_dlp; /* libdl(3DL) shared library handle */
70749f21d3Swesolows int sch_err; /* if negative entry, errno to return */
71749f21d3Swesolows fmd_scheme_ops_t sch_ops; /* scheme function pointers */
72749f21d3Swesolows } fmd_scheme_t;
73749f21d3Swesolows
74749f21d3Swesolows static fmd_scheme_t *sch_list; /* list of cached schemes */
75749f21d3Swesolows static char *g_root; /* fmd root dir */
761fe76c0bSwesolows static struct topo_hdl *g_thp;
77749f21d3Swesolows
78749f21d3Swesolows static long
fmd_scheme_notsup(void)79749f21d3Swesolows fmd_scheme_notsup(void)
80749f21d3Swesolows {
81749f21d3Swesolows errno = ENOTSUP;
82749f21d3Swesolows return (-1);
83749f21d3Swesolows }
84749f21d3Swesolows
85749f21d3Swesolows static int
fmd_scheme_nop(void)86749f21d3Swesolows fmd_scheme_nop(void)
87749f21d3Swesolows {
88749f21d3Swesolows return (0);
89749f21d3Swesolows }
90749f21d3Swesolows
91749f21d3Swesolows /*
92749f21d3Swesolows * Default values for the scheme ops. If a scheme function is not defined in
93749f21d3Swesolows * the module, then this operation is implemented using the default function.
94749f21d3Swesolows */
95749f21d3Swesolows static const fmd_scheme_ops_t _fmd_scheme_default_ops = {
96749f21d3Swesolows (int (*)())fmd_scheme_nop, /* sop_init */
97749f21d3Swesolows (void (*)())fmd_scheme_nop, /* sop_fini */
98749f21d3Swesolows (ssize_t (*)())fmd_scheme_notsup, /* sop_nvl2str */
99749f21d3Swesolows };
100749f21d3Swesolows
101749f21d3Swesolows /*
102749f21d3Swesolows * Scheme ops descriptions. These names and offsets are used by the function
103749f21d3Swesolows * fmd_scheme_rtld_init(), defined below, to load up a fmd_scheme_ops_t.
104749f21d3Swesolows */
105749f21d3Swesolows static const fmd_scheme_opd_t _fmd_scheme_ops[] = {
106749f21d3Swesolows { "fmd_fmri_init", offsetof(fmd_scheme_ops_t, sop_init) },
107749f21d3Swesolows { "fmd_fmri_fini", offsetof(fmd_scheme_ops_t, sop_fini) },
108749f21d3Swesolows { "fmd_fmri_nvl2str", offsetof(fmd_scheme_ops_t, sop_nvl2str) },
109749f21d3Swesolows { NULL, 0 }
110749f21d3Swesolows };
111749f21d3Swesolows
112749f21d3Swesolows static fmd_scheme_t *
fmd_scheme_create(const char * name)113749f21d3Swesolows fmd_scheme_create(const char *name)
114749f21d3Swesolows {
115749f21d3Swesolows fmd_scheme_t *sp;
116749f21d3Swesolows
117749f21d3Swesolows if ((sp = malloc(sizeof (fmd_scheme_t))) == NULL ||
118749f21d3Swesolows (sp->sch_name = strdup(name)) == NULL) {
119749f21d3Swesolows free(sp);
120749f21d3Swesolows return (NULL);
121749f21d3Swesolows }
122749f21d3Swesolows
123749f21d3Swesolows sp->sch_next = sch_list;
124749f21d3Swesolows sp->sch_dlp = NULL;
125749f21d3Swesolows sp->sch_err = 0;
126749f21d3Swesolows sp->sch_ops = _fmd_scheme_default_ops;
127749f21d3Swesolows
128749f21d3Swesolows sch_list = sp;
129749f21d3Swesolows return (sp);
130749f21d3Swesolows }
131749f21d3Swesolows
132749f21d3Swesolows static int
fmd_scheme_rtld_init(fmd_scheme_t * sp)133749f21d3Swesolows fmd_scheme_rtld_init(fmd_scheme_t *sp)
134749f21d3Swesolows {
135749f21d3Swesolows const fmd_scheme_opd_t *opd;
136749f21d3Swesolows void *p;
137749f21d3Swesolows
138749f21d3Swesolows for (opd = _fmd_scheme_ops; opd->opd_name != NULL; opd++) {
139749f21d3Swesolows if ((p = dlsym(sp->sch_dlp, opd->opd_name)) != NULL)
140749f21d3Swesolows *(void **)((uintptr_t)&sp->sch_ops + opd->opd_off) = p;
141749f21d3Swesolows }
142749f21d3Swesolows
143749f21d3Swesolows return (sp->sch_ops.sop_init());
144749f21d3Swesolows }
145749f21d3Swesolows
146749f21d3Swesolows static fmd_scheme_t *
fmd_scheme_lookup(const char * dir,const char * name)147749f21d3Swesolows fmd_scheme_lookup(const char *dir, const char *name)
148749f21d3Swesolows {
149749f21d3Swesolows fmd_scheme_t *sp;
150749f21d3Swesolows char path[PATH_MAX];
151749f21d3Swesolows
152749f21d3Swesolows for (sp = sch_list; sp != NULL; sp = sp->sch_next) {
153749f21d3Swesolows if (strcmp(name, sp->sch_name) == 0)
154749f21d3Swesolows return (sp);
155749f21d3Swesolows }
156749f21d3Swesolows
157749f21d3Swesolows if ((sp = fmd_scheme_create(name)) == NULL)
158749f21d3Swesolows return (NULL); /* errno is set for us */
159749f21d3Swesolows
160749f21d3Swesolows (void) snprintf(path, sizeof (path), "%s%s/%s.so",
161749f21d3Swesolows g_root ? g_root : "", dir, name);
162749f21d3Swesolows
163749f21d3Swesolows if (access(path, F_OK) != 0) {
164749f21d3Swesolows sp->sch_err = errno;
165749f21d3Swesolows return (sp);
166749f21d3Swesolows }
167749f21d3Swesolows
168749f21d3Swesolows if ((sp->sch_dlp = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_PARENT)) ==
169749f21d3Swesolows NULL) {
170749f21d3Swesolows sp->sch_err = ELIBACC;
171749f21d3Swesolows return (sp);
172749f21d3Swesolows }
173749f21d3Swesolows
174749f21d3Swesolows if (fmd_scheme_rtld_init(sp) != 0) {
175749f21d3Swesolows sp->sch_err = errno;
176749f21d3Swesolows (void) dlclose(sp->sch_dlp);
177749f21d3Swesolows sp->sch_dlp = NULL;
178749f21d3Swesolows }
179749f21d3Swesolows
180749f21d3Swesolows return (sp);
181749f21d3Swesolows }
182749f21d3Swesolows
183749f21d3Swesolows char *
sunFm_nvl2str(nvlist_t * nvl)184749f21d3Swesolows sunFm_nvl2str(nvlist_t *nvl)
185749f21d3Swesolows {
186749f21d3Swesolows fmd_scheme_t *sp;
187749f21d3Swesolows char c, *name, *s = NULL;
188749f21d3Swesolows ssize_t len;
189749f21d3Swesolows
190749f21d3Swesolows if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) {
191749f21d3Swesolows DEBUGMSGTL((MODNAME_STR, "fmri does not contain required "
192749f21d3Swesolows "'%s' nvpair\n", FM_FMRI_SCHEME));
193749f21d3Swesolows return (NULL);
194749f21d3Swesolows }
195749f21d3Swesolows
196749f21d3Swesolows if ((sp = fmd_scheme_lookup(DEFAULTSCHEMEDIR, name)) == NULL ||
197749f21d3Swesolows sp->sch_dlp == NULL || sp->sch_err != 0) {
198749f21d3Swesolows const char *msg =
199749f21d3Swesolows sp->sch_err == ELIBACC ? dlerror() : strerror(sp->sch_err);
200749f21d3Swesolows DEBUGMSGTL((MODNAME_STR, "cannot init '%s' scheme library to "
201749f21d3Swesolows "format fmri: %s\n", name, msg ? msg : "unknown error"));
202749f21d3Swesolows return (NULL);
203749f21d3Swesolows }
204749f21d3Swesolows
205749f21d3Swesolows if ((len = sp->sch_ops.sop_nvl2str(nvl, &c, sizeof (c))) == -1 ||
206749f21d3Swesolows (s = malloc(len + 1)) == NULL ||
207749f21d3Swesolows sp->sch_ops.sop_nvl2str(nvl, s, len + 1) == -1) {
208749f21d3Swesolows DEBUGMSGTL((MODNAME_STR, "cannot format fmri using scheme '%s'",
209749f21d3Swesolows name));
210749f21d3Swesolows free(s);
211749f21d3Swesolows return (NULL);
212749f21d3Swesolows }
213749f21d3Swesolows
214749f21d3Swesolows return (s);
215749f21d3Swesolows }
216749f21d3Swesolows
217749f21d3Swesolows void *
fmd_fmri_alloc(size_t size)218749f21d3Swesolows fmd_fmri_alloc(size_t size)
219749f21d3Swesolows {
220749f21d3Swesolows return (malloc(size));
221749f21d3Swesolows }
222749f21d3Swesolows
223749f21d3Swesolows void *
fmd_fmri_zalloc(size_t size)224749f21d3Swesolows fmd_fmri_zalloc(size_t size)
225749f21d3Swesolows {
226749f21d3Swesolows void *data;
227749f21d3Swesolows
228749f21d3Swesolows if ((data = malloc(size)) != NULL)
229749f21d3Swesolows bzero(data, size);
230749f21d3Swesolows
231749f21d3Swesolows return (data);
232749f21d3Swesolows }
233749f21d3Swesolows
234749f21d3Swesolows /*ARGSUSED*/
235749f21d3Swesolows void
fmd_fmri_free(void * data,size_t size)236749f21d3Swesolows fmd_fmri_free(void *data, size_t size)
237749f21d3Swesolows {
238749f21d3Swesolows free(data);
239749f21d3Swesolows }
240749f21d3Swesolows
241749f21d3Swesolows int
fmd_fmri_error(int err)242749f21d3Swesolows fmd_fmri_error(int err)
243749f21d3Swesolows {
244749f21d3Swesolows errno = err;
245749f21d3Swesolows return (-1);
246749f21d3Swesolows }
247749f21d3Swesolows
248749f21d3Swesolows char *
fmd_fmri_strescape(const char * s)249749f21d3Swesolows fmd_fmri_strescape(const char *s)
250749f21d3Swesolows {
251749f21d3Swesolows return (strdup(s));
252749f21d3Swesolows }
253749f21d3Swesolows
254749f21d3Swesolows char *
fmd_fmri_strdup(const char * s)255749f21d3Swesolows fmd_fmri_strdup(const char *s)
256749f21d3Swesolows {
257749f21d3Swesolows return (strdup(s));
258749f21d3Swesolows }
259749f21d3Swesolows
260749f21d3Swesolows void
fmd_fmri_strfree(char * s)261749f21d3Swesolows fmd_fmri_strfree(char *s)
262749f21d3Swesolows {
263749f21d3Swesolows free(s);
264749f21d3Swesolows }
265749f21d3Swesolows
266749f21d3Swesolows const char *
fmd_fmri_get_rootdir(void)267749f21d3Swesolows fmd_fmri_get_rootdir(void)
268749f21d3Swesolows {
269749f21d3Swesolows return (g_root ? g_root : "");
270749f21d3Swesolows }
271749f21d3Swesolows
272749f21d3Swesolows const char *
fmd_fmri_get_platform(void)273749f21d3Swesolows fmd_fmri_get_platform(void)
274749f21d3Swesolows {
275749f21d3Swesolows static char platform[MAXNAMELEN];
276749f21d3Swesolows
277749f21d3Swesolows if (platform[0] == '\0')
278749f21d3Swesolows (void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
279749f21d3Swesolows
280749f21d3Swesolows return (platform);
281749f21d3Swesolows }
282749f21d3Swesolows
283749f21d3Swesolows uint64_t
fmd_fmri_get_drgen(void)284749f21d3Swesolows fmd_fmri_get_drgen(void)
285749f21d3Swesolows {
286749f21d3Swesolows return (0);
287749f21d3Swesolows }
288749f21d3Swesolows
289749f21d3Swesolows int
fmd_fmri_set_errno(int err)290749f21d3Swesolows fmd_fmri_set_errno(int err)
291749f21d3Swesolows {
292749f21d3Swesolows errno = err;
293749f21d3Swesolows return (-1);
294749f21d3Swesolows }
295749f21d3Swesolows
29630698f33Swesolows /*ARGSUSED*/
297749f21d3Swesolows void
fmd_fmri_warn(const char * format,...)298749f21d3Swesolows fmd_fmri_warn(const char *format, ...)
299749f21d3Swesolows {
300749f21d3Swesolows }
3011fe76c0bSwesolows
3021fe76c0bSwesolows struct topo_hdl *
fmd_fmri_topo_hold(int version)303*24db4641Seschrock fmd_fmri_topo_hold(int version)
3041fe76c0bSwesolows {
3051fe76c0bSwesolows int err;
3061fe76c0bSwesolows
307*24db4641Seschrock if (version != TOPO_VERSION)
308*24db4641Seschrock return (NULL);
309*24db4641Seschrock
3101fe76c0bSwesolows if (g_thp == NULL) {
3111fe76c0bSwesolows if ((g_thp = topo_open(TOPO_VERSION, "/", &err)) == NULL) {
3121fe76c0bSwesolows DEBUGMSGTL((MODNAME_STR, "topo_open failed: %s\n",
3131fe76c0bSwesolows topo_strerror(err)));
3141fe76c0bSwesolows return (NULL);
3151fe76c0bSwesolows }
3161fe76c0bSwesolows }
3171fe76c0bSwesolows
3181fe76c0bSwesolows return (g_thp);
3191fe76c0bSwesolows }
320*24db4641Seschrock
321*24db4641Seschrock /*ARGSUSED*/
322*24db4641Seschrock void
fmd_fmri_topo_rele(struct topo_hdl * thp)323*24db4641Seschrock fmd_fmri_topo_rele(struct topo_hdl *thp)
324*24db4641Seschrock {
325*24db4641Seschrock /* nothing to do */
326*24db4641Seschrock }
327