Mercurial > illumos > illumos-gate
annotate usr/src/lib/fm/topo/libtopo/common/mod.c @ 12979:ab9ae749152f
PSARC/2009/617 Software Events Notification Parameters CLI
PSARC/2009/618 snmp-notify: SNMP Notification Daemon for Software Events
PSARC/2009/619 smtp-notify: Email Notification Daemon for Software Events
PSARC/2010/225 fmd for non-global Solaris zones
PSARC/2010/226 Solaris Instance UUID
PSARC/2010/227 nvlist_nvflag(3NVPAIR)
PSARC/2010/228 libfmevent additions
PSARC/2010/257 sysevent_evc_setpropnvl and sysevent_evc_getpropnvl
PSARC/2010/265 FMRI and FMA Event Stabilty, 'ireport' category 1 event class, and the 'sw' FMRI scheme
PSARC/2010/278 FMA/SMF integration: instance state transitions
PSARC/2010/279 Modelling panics within FMA
PSARC/2010/290 logadm.conf upgrade
6392476 fmdump needs to pretty-print
6393375 userland ereport/ireport event generation interfaces
6445732 Add email notification agent for FMA and software events
6804168 RFE: Allow an efficient means to monitor SMF services status changes
6866661 scf_values_destroy(3SCF) will segfault if is passed NULL
6884709 Add snmp notification agent for FMA and software events
6884712 Add private interface to tap into libfmd_msg macro expansion capabilities
6897919 fmd to run in a non-global zone
6897937 fmd use of non-private doors is not safe
6900081 add a UUID to Solaris kernel image for use in crashdump identification
6914884 model panic events as a defect diagnosis in FMA
6944862 fmd_case_open_uuid, fmd_case_uuisresolved, fmd_nvl_create_defect
6944866 log legacy sysevents in fmd
6944867 enumerate svc scheme in topo
6944868 software-diagnosis and software-response fmd modules
6944870 model SMF maintenance state as a defect diagnosis in FMA
6944876 savecore runs in foreground for systems with zfs root and dedicated dump
6965796 Implement notification parameters for SMF state transitions and FMA events
6968287 SUN-FM-MIB.mib needs to be updated to reflect Oracle information
6972331 logadm.conf upgrade PSARC/2010/290
author | Gavin Maltby <gavin.maltby@oracle.com> |
---|---|
date | Fri, 30 Jul 2010 17:04:17 +1000 |
parents | be69f645ce17 |
children |
rev | line source |
---|---|
1414 | 1 /* |
2 * CDDL HEADER START | |
3 * | |
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. | |
7 * | |
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. | |
12 * | |
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] | |
18 * | |
19 * CDDL HEADER END | |
20 */ | |
21 | |
22 /* | |
12979
ab9ae749152f
PSARC/2009/617 Software Events Notification Parameters CLI
Gavin Maltby <gavin.maltby@oracle.com>
parents:
11050
diff
changeset
|
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. |
1414 | 24 */ |
25 | |
26 #include <limits.h> | |
27 #include <strings.h> | |
28 #include <unistd.h> | |
29 #include <libnvpair.h> | |
30 #include <fm/topo_mod.h> | |
31 #include <sys/fm/protocol.h> | |
32 | |
33 #include <fcntl.h> | |
34 #include <sys/types.h> | |
35 #include <sys/stat.h> | |
36 #include <sys/objfs.h> | |
37 #include <sys/modctl.h> | |
38 #include <libelf.h> | |
39 #include <gelf.h> | |
40 | |
3062 | 41 #include <topo_method.h> |
3323 | 42 #include <topo_subr.h> |
3062 | 43 #include <mod.h> |
1414 | 44 |
45 static int mod_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t, | |
3062 | 46 topo_instance_t, void *, void *); |
1414 | 47 static void mod_release(topo_mod_t *, tnode_t *); |
48 static int mod_fmri_create_meth(topo_mod_t *, tnode_t *, topo_version_t, | |
49 nvlist_t *, nvlist_t **); | |
3323 | 50 static int mod_fmri_nvl2str(topo_mod_t *, tnode_t *, topo_version_t, |
51 nvlist_t *, nvlist_t **); | |
1414 | 52 |
53 static const topo_method_t mod_methods[] = { | |
54 { TOPO_METH_FMRI, TOPO_METH_FMRI_DESC, TOPO_METH_FMRI_VERSION, | |
55 TOPO_STABILITY_INTERNAL, mod_fmri_create_meth }, | |
3323 | 56 { TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION, |
57 TOPO_STABILITY_INTERNAL, mod_fmri_nvl2str }, | |
1414 | 58 { NULL } |
59 }; | |
60 | |
3062 | 61 static const topo_modops_t mod_modops = |
62 { mod_enum, mod_release }; | |
1414 | 63 static const topo_modinfo_t mod_info = |
3062 | 64 { "mod", FM_FMRI_SCHEME_MOD, MOD_VERSION, &mod_modops }; |
1414 | 65 |
3062 | 66 int |
67 mod_init(topo_mod_t *mod, topo_version_t version) | |
1414 | 68 { |
3062 | 69 if (getenv("TOPOMODDEBUG")) |
70 topo_mod_setdebug(mod); | |
1414 | 71 topo_mod_dprintf(mod, "initializing mod builtin\n"); |
72 | |
3062 | 73 if (version != MOD_VERSION) |
74 return (topo_mod_seterrno(mod, EMOD_VER_NEW)); | |
75 | |
76 if (topo_mod_register(mod, &mod_info, TOPO_VERSION) != 0) { | |
1414 | 77 topo_mod_dprintf(mod, "failed to register mod_info: " |
78 "%s\n", topo_mod_errmsg(mod)); | |
3062 | 79 return (-1); /* mod errno already set */ |
1414 | 80 } |
3062 | 81 |
82 return (0); | |
1414 | 83 } |
84 | |
85 void | |
86 mod_fini(topo_mod_t *mod) | |
87 { | |
88 topo_mod_unregister(mod); | |
89 } | |
90 | |
91 /*ARGSUSED*/ | |
92 static int | |
93 mod_enum(topo_mod_t *mod, tnode_t *pnode, const char *name, | |
3062 | 94 topo_instance_t min, topo_instance_t max, void *notused1, void *notused2) |
1414 | 95 { |
12979
ab9ae749152f
PSARC/2009/617 Software Events Notification Parameters CLI
Gavin Maltby <gavin.maltby@oracle.com>
parents:
11050
diff
changeset
|
96 /* |
ab9ae749152f
PSARC/2009/617 Software Events Notification Parameters CLI
Gavin Maltby <gavin.maltby@oracle.com>
parents:
11050
diff
changeset
|
97 * Methods are registered, but there is no enumeration. Should |
ab9ae749152f
PSARC/2009/617 Software Events Notification Parameters CLI
Gavin Maltby <gavin.maltby@oracle.com>
parents:
11050
diff
changeset
|
98 * enumeration be added be sure to cater for global vs non-global |
ab9ae749152f
PSARC/2009/617 Software Events Notification Parameters CLI
Gavin Maltby <gavin.maltby@oracle.com>
parents:
11050
diff
changeset
|
99 * zones. |
ab9ae749152f
PSARC/2009/617 Software Events Notification Parameters CLI
Gavin Maltby <gavin.maltby@oracle.com>
parents:
11050
diff
changeset
|
100 */ |
1414 | 101 (void) topo_method_register(mod, pnode, mod_methods); |
102 return (0); | |
103 } | |
104 | |
105 static void | |
106 mod_release(topo_mod_t *mod, tnode_t *node) | |
107 { | |
108 topo_method_unregister_all(mod, node); | |
109 } | |
110 | |
3323 | 111 static int |
112 mod_binary_path_get(topo_mod_t *mp, const char *objpath) | |
1414 | 113 { |
114 Elf *elf = NULL; | |
115 Elf_Scn *scn = NULL; | |
116 GElf_Ehdr ehdr; | |
117 GElf_Shdr shdr; | |
118 int fd; | |
119 | |
120 if ((fd = open(objpath, O_RDONLY)) < 0) { | |
3323 | 121 topo_mod_dprintf(mp, "unable to open %s\n", objpath); |
122 return (-1); | |
1414 | 123 } |
3323 | 124 |
1414 | 125 if (elf_version(EV_CURRENT) == EV_NONE) { |
126 topo_mod_dprintf(mp, "Elf version out of whack\n"); | |
127 goto mbpg_bail; | |
128 } | |
129 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { | |
130 topo_mod_dprintf(mp, "elf_begin failed\n"); | |
131 goto mbpg_bail; | |
132 } | |
133 if ((gelf_getehdr(elf, &ehdr)) == NULL) { | |
134 topo_mod_dprintf(mp, "gelf_getehdr failed\n"); | |
135 goto mbpg_bail; | |
136 } | |
137 scn = elf_getscn(elf, 0); /* "seek" to start of sections */ | |
138 while ((scn = elf_nextscn(elf, scn)) != NULL) { | |
139 const char *sh_name; | |
140 if (gelf_getshdr(scn, &shdr) == NULL) { | |
141 topo_mod_dprintf(mp, "gelf_getshdr failed\n"); | |
142 goto mbpg_bail; | |
143 } | |
144 if (shdr.sh_type != SHT_PROGBITS) | |
145 continue; | |
146 sh_name = elf_strptr(elf, | |
147 ehdr.e_shstrndx, (size_t)shdr.sh_name); | |
148 if (strcmp(sh_name, ".filename") != 0) | |
149 continue; | |
3323 | 150 if (elf_getdata(scn, NULL) == NULL) { |
1414 | 151 topo_mod_dprintf(mp, "no filename data"); |
152 break; | |
153 } | |
154 break; | |
155 } | |
11050
be69f645ce17
6894028 Some fm libraries are not lint clean
Robert Johnston <Robert.Johnston@Sun.COM>
parents:
10462
diff
changeset
|
156 (void) elf_end(elf); |
1414 | 157 (void) close(fd); |
3323 | 158 return (0); |
1414 | 159 |
160 mbpg_bail: | |
161 if (elf != NULL) | |
11050
be69f645ce17
6894028 Some fm libraries are not lint clean
Robert Johnston <Robert.Johnston@Sun.COM>
parents:
10462
diff
changeset
|
162 (void) elf_end(elf); |
1414 | 163 if (fd >= 0) |
164 (void) close(fd); | |
165 (void) topo_mod_seterrno(mp, EMOD_METHOD_INVAL); | |
3323 | 166 return (-1); |
1414 | 167 } |
168 | |
169 static int | |
170 mod_nvl_data(topo_mod_t *mp, nvlist_t *out, const char *path) | |
171 { | |
172 struct modinfo mi; | |
173 struct stat64 s; | |
174 int id, e; | |
175 | |
176 if (stat64(path, &s) < 0) { | |
177 topo_mod_dprintf(mp, | |
178 "No system object file for driver %s", path); | |
179 return (topo_mod_seterrno(mp, EMOD_METHOD_INVAL)); | |
180 } | |
181 | |
182 id = OBJFS_MODID(s.st_ino); | |
183 mi.mi_id = mi.mi_nextid = id; | |
184 mi.mi_info = MI_INFO_ONE | MI_INFO_NOBASE; | |
185 if (modctl(MODINFO, id, &mi) < 0) { | |
186 return (topo_mod_seterrno(mp, EMOD_METHOD_INVAL)); | |
187 } | |
188 mi.mi_name[MODMAXNAMELEN - 1] = '\0'; | |
189 mi.mi_msinfo[0].msi_linkinfo[MODMAXNAMELEN - 1] = '\0'; | |
190 e = nvlist_add_string(out, FM_FMRI_SCHEME, FM_FMRI_SCHEME_MOD); | |
191 e |= nvlist_add_uint8(out, FM_VERSION, FM_MOD_SCHEME_VERSION); | |
192 e |= nvlist_add_int32(out, FM_FMRI_MOD_ID, id); | |
193 e |= nvlist_add_string(out, FM_FMRI_MOD_NAME, mi.mi_name); | |
194 e |= nvlist_add_string(out, | |
195 FM_FMRI_MOD_DESC, mi.mi_msinfo[0].msi_linkinfo); | |
196 if (e != 0) | |
197 return (topo_mod_seterrno(mp, EMOD_FMRI_NVL)); | |
198 | |
199 return (0); | |
200 } | |
201 | |
202 static nvlist_t * | |
203 mod_fmri_create(topo_mod_t *mp, const char *driver) | |
204 { | |
205 nvlist_t *out = NULL; | |
206 char objpath[PATH_MAX]; | |
207 | |
3062 | 208 if (topo_mod_nvalloc(mp, &out, NV_UNIQUE_NAME) != 0) { |
1414 | 209 (void) topo_mod_seterrno(mp, EMOD_FMRI_NVL); |
210 goto mfc_bail; | |
211 } | |
212 | |
213 (void) snprintf(objpath, PATH_MAX, "%s/%s/object", OBJFS_ROOT, driver); | |
214 | |
3323 | 215 /* |
216 * Validate the module object ELF header if possible | |
217 */ | |
218 if (mod_binary_path_get(mp, objpath) < 0) | |
1414 | 219 goto mfc_bail; |
220 | |
3323 | 221 if (mod_nvl_data(mp, out, objpath) < 0) { |
222 topo_mod_dprintf(mp, "failed to get modinfo for %s", driver); | |
1414 | 223 goto mfc_bail; |
224 } | |
225 | |
226 return (out); | |
227 | |
228 mfc_bail: | |
229 nvlist_free(out); | |
230 return (NULL); | |
231 } | |
232 | |
233 /*ARGSUSED*/ | |
234 static int | |
235 mod_fmri_create_meth(topo_mod_t *mp, tnode_t *node, topo_version_t version, | |
236 nvlist_t *in, nvlist_t **out) | |
237 { | |
238 nvlist_t *args; | |
239 nvlist_t *modnvl; | |
240 char *driver; | |
241 | |
242 if (version > TOPO_METH_FMRI_VERSION) | |
243 return (topo_mod_seterrno(mp, EMOD_VER_NEW)); | |
244 | |
245 if (nvlist_lookup_nvlist(in, TOPO_METH_FMRI_ARG_NVL, &args) != 0 || | |
246 nvlist_lookup_string(args, "DRIVER", &driver) != 0) { | |
247 topo_mod_dprintf(mp, "no DRIVER string in method argument\n"); | |
248 return (topo_mod_seterrno(mp, EMOD_METHOD_INVAL)); | |
249 } | |
250 | |
251 modnvl = mod_fmri_create(mp, driver); | |
252 if (modnvl == NULL) { | |
253 *out = NULL; | |
254 topo_mod_dprintf(mp, "failed to create contained mod FMRI\n"); | |
3323 | 255 return (-1); |
1414 | 256 } |
257 *out = modnvl; | |
258 return (0); | |
259 } | |
3323 | 260 |
261 #define MAXINTSTR 11 | |
262 | |
263 static ssize_t | |
264 fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) | |
265 { | |
266 nvlist_t *anvl = NULL; | |
10462
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
267 nvpair_t *apair; |
3323 | 268 uint8_t version; |
269 ssize_t size = 0; | |
270 int32_t modid; | |
10462
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
271 char *modname = NULL, *aname, *aval; |
3323 | 272 char numbuf[MAXINTSTR]; |
273 int err; | |
274 | |
275 if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || | |
276 version > FM_MOD_SCHEME_VERSION) | |
277 return (-1); | |
278 | |
279 /* Get authority, if present */ | |
280 err = nvlist_lookup_nvlist(nvl, FM_FMRI_AUTHORITY, &anvl); | |
281 if (err != 0 && err != ENOENT) | |
282 return (-1); | |
283 | |
284 /* | |
285 * For brevity, we only include the module name and id | |
286 * present in the FMRI in our output string. The FMRI | |
287 * also has data on the package containing the module. | |
288 */ | |
289 | |
290 /* There must be a module name */ | |
291 err = nvlist_lookup_string(nvl, FM_FMRI_MOD_NAME, &modname); | |
292 if (err != 0 || modname == NULL) | |
293 return (-1); | |
294 | |
295 /* There must be a module id */ | |
296 err = nvlist_lookup_int32(nvl, FM_FMRI_MOD_ID, &modid); | |
297 if (err != 0) | |
298 return (-1); | |
299 | |
300 /* mod:// */ | |
301 topo_fmristr_build(&size, buf, buflen, FM_FMRI_SCHEME_MOD, NULL, "://"); | |
302 | |
303 /* authority, if any */ | |
10462
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
304 if (anvl != NULL) { |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
305 for (apair = nvlist_next_nvpair(anvl, NULL); |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
306 apair != NULL; apair = nvlist_next_nvpair(anvl, apair)) { |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
307 if (nvpair_type(apair) != DATA_TYPE_STRING || |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
308 nvpair_value_string(apair, &aval) != 0) |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
309 continue; |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
310 aname = nvpair_name(apair); |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
311 topo_fmristr_build(&size, buf, buflen, ":", NULL, NULL); |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
312 topo_fmristr_build(&size, buf, buflen, "=", |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
313 aname, aval); |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
314 } |
ec0e4f3134ef
PSARC/2007/650 Product Serial Number for FMRI
Cheng Sean Ye <Sean.Ye@Sun.COM>
parents:
7197
diff
changeset
|
315 } |
3323 | 316 |
317 /* module parts */ | |
318 topo_fmristr_build(&size, buf, buflen, modname, | |
319 "/" FM_FMRI_MOD_NAME "=", "/"); | |
320 | |
321 (void) snprintf(numbuf, MAXINTSTR, "%d", modid); | |
322 topo_fmristr_build(&size, buf, buflen, numbuf, FM_FMRI_MOD_ID "=", | |
323 NULL); | |
324 | |
325 return (size); | |
326 } | |
327 | |
328 /*ARGSUSED*/ | |
329 static int | |
330 mod_fmri_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version, | |
331 nvlist_t *nvl, nvlist_t **out) | |
332 { | |
333 ssize_t len; | |
334 char *name = NULL; | |
335 nvlist_t *fmristr; | |
336 | |
337 if (version > TOPO_METH_NVL2STR_VERSION) | |
338 return (topo_mod_seterrno(mod, EMOD_VER_NEW)); | |
339 | |
340 if ((len = fmri_nvl2str(nvl, NULL, 0)) == 0 || | |
341 (name = topo_mod_alloc(mod, len + 1)) == NULL || | |
342 fmri_nvl2str(nvl, name, len + 1) == 0) { | |
343 if (name != NULL) | |
344 topo_mod_free(mod, name, len + 1); | |
345 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); | |
346 } | |
347 | |
348 if (topo_mod_nvalloc(mod, &fmristr, NV_UNIQUE_NAME) != 0) | |
349 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); | |
350 if (nvlist_add_string(fmristr, "fmri-string", name) != 0) { | |
351 topo_mod_free(mod, name, len + 1); | |
352 nvlist_free(fmristr); | |
353 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); | |
354 } | |
355 topo_mod_free(mod, name, len + 1); | |
356 *out = fmristr; | |
357 | |
358 return (0); | |
359 } |