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]
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>
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"
52 #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE
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);
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 */
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 */
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
;
79 fmd_scheme_notsup(void)
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
) },
112 static fmd_scheme_t
*
113 fmd_scheme_create(const char *name
)
117 if ((sp
= malloc(sizeof (fmd_scheme_t
))) == NULL
||
118 (sp
->sch_name
= strdup(name
)) == NULL
) {
123 sp
->sch_next
= sch_list
;
126 sp
->sch_ops
= _fmd_scheme_default_ops
;
133 fmd_scheme_rtld_init(fmd_scheme_t
*sp
)
135 const fmd_scheme_opd_t
*opd
;
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
)
152 for (sp
= sch_list
; sp
!= NULL
; sp
= sp
->sch_next
) {
153 if (strcmp(name
, sp
->sch_name
) == 0)
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) {
168 if ((sp
->sch_dlp
= dlopen(path
, RTLD_LOCAL
| RTLD_NOW
| RTLD_PARENT
)) ==
170 sp
->sch_err
= ELIBACC
;
174 if (fmd_scheme_rtld_init(sp
) != 0) {
176 (void) dlclose(sp
->sch_dlp
);
184 sunFm_nvl2str(nvlist_t
*nvl
)
187 char c
, *name
, *s
= NULL
;
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
));
196 if ((sp
= fmd_scheme_lookup(DEFAULTSCHEMEDIR
, name
)) == NULL
||
197 sp
->sch_dlp
== NULL
|| sp
->sch_err
!= 0) {
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"));
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'",
218 fmd_fmri_alloc(size_t size
)
220 return (malloc(size
));
224 fmd_fmri_zalloc(size_t size
)
228 if ((data
= malloc(size
)) != NULL
)
236 fmd_fmri_free(void *data
, size_t size
)
242 fmd_fmri_error(int err
)
249 fmd_fmri_strescape(const char *s
)
255 fmd_fmri_strdup(const char *s
)
261 fmd_fmri_strfree(char *s
)
267 fmd_fmri_get_rootdir(void)
269 return (g_root
? g_root
: "");
273 fmd_fmri_get_platform(void)
275 static char platform
[MAXNAMELEN
];
277 if (platform
[0] == '\0')
278 (void) sysinfo(SI_PLATFORM
, platform
, sizeof (platform
));
284 fmd_fmri_get_drgen(void)
290 fmd_fmri_set_errno(int err
)
298 fmd_fmri_warn(const char *format
, ...)
303 fmd_fmri_topo_hold(int version
)
307 if (version
!= TOPO_VERSION
)
311 if ((g_thp
= topo_open(TOPO_VERSION
, "/", &err
)) == NULL
) {
312 DEBUGMSGTL((MODNAME_STR
, "topo_open failed: %s\n",
313 topo_strerror(err
)));
323 fmd_fmri_topo_rele(struct topo_hdl
*thp
)