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 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <libintl.h>
27 #include <libnvpair.h>
28 #include <libscf.h>
29 #include <libscf_priv.h>
30 #include <libuutil.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <string.h>
34
35 #include "notify_params.h"
36
37 static struct events {
38 const char *s;
39 int32_t c;
40 } smf_st_events[] = {
41 { "to-uninitialized", SCF_TRANS(0, SCF_STATE_UNINIT) },
42 { "from-uninitialized", SCF_TRANS(SCF_STATE_UNINIT, 0) },
43 { "uninitialized", SCF_TRANS(SCF_STATE_UNINIT, SCF_STATE_UNINIT) },
44 { "to-maintenance", SCF_TRANS(0, SCF_STATE_MAINT) },
45 { "from-maintenance", SCF_TRANS(SCF_STATE_MAINT, 0) },
46 { "maintenance", SCF_TRANS(SCF_STATE_MAINT, SCF_STATE_MAINT) },
47 { "to-offline", SCF_TRANS(0, SCF_STATE_OFFLINE) },
48 { "from-offline", SCF_TRANS(SCF_STATE_OFFLINE, 0) },
49 { "offline", SCF_TRANS(SCF_STATE_OFFLINE, SCF_STATE_OFFLINE) },
50 { "to-disabled", SCF_TRANS(0, SCF_STATE_DISABLED) },
51 { "from-disabled", SCF_TRANS(SCF_STATE_DISABLED, 0) },
52 { "disabled", SCF_TRANS(SCF_STATE_DISABLED, SCF_STATE_DISABLED) },
53 { "to-online", SCF_TRANS(0, SCF_STATE_ONLINE) },
54 { "from-online", SCF_TRANS(SCF_STATE_ONLINE, 0) },
55 { "online", SCF_TRANS(SCF_STATE_ONLINE, SCF_STATE_ONLINE) },
56 { "to-degraded", SCF_TRANS(0, SCF_STATE_DEGRADED) },
57 { "from-degraded", SCF_TRANS(SCF_STATE_DEGRADED, 0) },
58 { "degraded", SCF_TRANS(SCF_STATE_DEGRADED, SCF_STATE_DEGRADED) },
59 { "to-all", SCF_TRANS(0, SCF_STATE_ALL) },
60 { "from-all", SCF_TRANS(SCF_STATE_ALL, 0) },
61 { "all", SCF_TRANS(SCF_STATE_ALL, SCF_STATE_ALL) },
62 { NULL, 0 }
63 };
64
65 static struct fma_tags {
66 const char *t;
67 const char *s;
68 } fma_tags[] = {
69 { "problem-diagnosed", "list.suspect" },
70 { "problem-updated", "list.updated" },
71 { "problem-repaired", "list.repaired" },
72 { "problem-resolved", "list.resolved" },
73 { NULL, NULL }
74 };
75
76 static char *fma_classes[] = {
77 "list.",
78 "ireport.",
79 NULL
80 };
81
82 /*
83 * get_fma_tag()
84 * return a pointer to the fma tag at the passed index. NULL if no entry exist
85 * for index
86 */
87 const char *
get_fma_tag(uint32_t index)88 get_fma_tag(uint32_t index)
89 {
90 if (index >= (sizeof (fma_tags) / sizeof (struct fma_tags)))
91 return (NULL);
92
93 return (fma_tags[index].t);
94 }
95
96 /*
97 * get_fma_class()
98 * return a pointer to the fma class at the passed index. NULL if no entry exist
99 * for index
100 */
101 const char *
get_fma_class(uint32_t index)102 get_fma_class(uint32_t index)
103 {
104 if (index >= (sizeof (fma_tags) / sizeof (struct fma_tags)))
105 return (NULL);
106
107 return (fma_tags[index].s);
108 }
109
110 /*
111 * is_fma_token()
112 * check if the parameter is an fma token by comparing with the
113 * fma_classes[] and the fma_tags[] arrays.
114 */
115 int
is_fma_token(const char * t)116 is_fma_token(const char *t)
117 {
118 int i;
119
120 for (i = 0; fma_classes[i]; ++i)
121 if (strncmp(t, fma_classes[i], strlen(fma_classes[i])) == 0)
122 return (1);
123
124 for (i = 0; fma_tags[i].t; ++i)
125 if (strcmp(t, fma_tags[i].t) == 0)
126 return (1);
127
128 return (0);
129 }
130
131 /*
132 * has_fma_tag()
133 * returns 1 if there is an fma tag for the passed class, 0 otherwise
134 */
135 int
has_fma_tag(const char * c)136 has_fma_tag(const char *c)
137 {
138 int i;
139
140 for (i = 0; fma_tags[i].s; ++i)
141 if (strcmp(c, fma_tags[i].s) == 0)
142 return (1);
143
144 return (0);
145 }
146
147 const char *
de_tag(const char * tag)148 de_tag(const char *tag)
149 {
150 int i;
151
152 for (i = 0; fma_tags[i].t; ++i)
153 if (strcmp(tag, fma_tags[i].t) == 0)
154 return (fma_tags[i].s);
155
156 return (tag);
157 }
158
159 const char *
re_tag(const char * fma_event)160 re_tag(const char *fma_event)
161 {
162 int i;
163
164 for (i = 0; fma_tags[i].s; ++i)
165 if (strcmp(fma_event, fma_tags[i].s) == 0)
166 return (fma_tags[i].t);
167
168 return (fma_event);
169 }
170
171 int32_t
string_to_tset(const char * str)172 string_to_tset(const char *str)
173 {
174 int i;
175
176 for (i = 0; smf_st_events[i].s != NULL; ++i) {
177 if (strcmp(str, smf_st_events[i].s) == 0)
178 return (smf_st_events[i].c);
179 }
180
181 return (0);
182 }
183
184 const char *
tset_to_string(int32_t t)185 tset_to_string(int32_t t)
186 {
187 int i;
188
189 for (i = 0; smf_st_events[i].s != NULL; ++i) {
190 if (smf_st_events[i].c == t)
191 return (smf_st_events[i].s);
192 }
193
194 return (NULL);
195 }
196
197 void
safe_printf(const char * fmt,...)198 safe_printf(const char *fmt, ...)
199 {
200 va_list va;
201
202 va_start(va, fmt);
203 if (vprintf(fmt, va) < 0)
204 uu_die(gettext("Error writing to stdout"));
205 va_end(va);
206 }
207
208 static uint32_t
notify_params_get_version(nvlist_t * nvl)209 notify_params_get_version(nvlist_t *nvl)
210 {
211 uint32_t v;
212
213 if (nvl == NULL)
214 return (0xFFFFFFFFU);
215
216 if (nvlist_lookup_uint32(nvl, SCF_NOTIFY_NAME_VERSION, &v) != 0)
217 return (0xFFFFFFFFU);
218 else
219 return (v);
220 }
221
222 static void
nvpair_print(nvpair_t * p)223 nvpair_print(nvpair_t *p)
224 {
225 char **v;
226 uint_t n;
227 int i;
228
229 safe_printf(" %s:", nvpair_name(p));
230 (void) nvpair_value_string_array(p, &v, &n);
231 for (i = 0; i < n; ++i) {
232 safe_printf(" %s", v[i]);
233 }
234 safe_printf("\n");
235 }
236
237 static void
params_type_print(nvlist_t * p,const char * name,const char * fmri)238 params_type_print(nvlist_t *p, const char *name, const char *fmri)
239 {
240 nvpair_t *tnvp, *nvp;
241 nvlist_t *nvl;
242 boolean_t *a;
243 uint_t n;
244 int has_output = 0;
245
246 /* for each event e print all notification parameters */
247 for (tnvp = nvlist_next_nvpair(p, NULL); tnvp != NULL;
248 tnvp = nvlist_next_nvpair(p, tnvp)) {
249 /* We only want the NVLIST memebers */
250 if (nvpair_type(tnvp) != DATA_TYPE_NVLIST)
251 continue;
252
253 if (nvpair_value_nvlist(tnvp, &nvl) != 0)
254 uu_die("nvpair_value_nvlist");
255
256 if (!has_output) {
257 if (fmri == NULL) {
258 safe_printf(gettext(" Event: %s\n"), name);
259 } else {
260 safe_printf(gettext(
261 " Event: %s (source: %s)\n"),
262 name, fmri);
263 }
264 }
265
266 has_output = 1;
267
268 safe_printf(gettext(" Notification Type: %s\n"),
269 nvpair_name(tnvp));
270
271 if (nvlist_lookup_boolean_array(nvl, PARAM_ACTIVE, &a, &n) != 0)
272 uu_warn(gettext("Missing 'active' property"));
273 else
274 safe_printf(gettext(" Active: %s\n"),
275 *a ? "true" : "false");
276
277 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
278 nvp = nvlist_next_nvpair(nvl, nvp)) {
279 if (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)
280 continue;
281 nvpair_print(nvp);
282 }
283 safe_printf("\n");
284 }
285 }
286
287 void
listnotify_print(nvlist_t * nvl,const char * event)288 listnotify_print(nvlist_t *nvl, const char *event)
289 {
290 char *fmri;
291 nvlist_t **params;
292 size_t n;
293 int32_t tset;
294 int i;
295
296 /*
297 * Check the nvl we got is from a version we understand
298 */
299 if (nvl != NULL && notify_params_get_version(nvl) !=
300 SCF_NOTIFY_PARAMS_VERSION)
301 uu_die(gettext("libscf(3LIB) mismatch\n"));
302
303 if (nvl != NULL && nvlist_lookup_nvlist_array(nvl, SCF_NOTIFY_PARAMS,
304 ¶ms, &n) != 0)
305 /* Sanity check. If we get here nvl is bad! */
306 uu_die(gettext("nvlist_lookup_nvlist_array\n"));
307
308 if (event == NULL) {
309 /* this is an SMF state transition nvlist */
310 for (i = 0; i < n; ++i) {
311 nvlist_t *p = *(params + i);
312
313 if (nvlist_lookup_string(p,
314 SCF_NOTIFY_PARAMS_SOURCE_NAME, &fmri) != 0)
315 fmri = NULL;
316 if (nvlist_lookup_int32(p, SCF_NOTIFY_NAME_TSET,
317 &tset) != 0)
318 uu_die("nvlist_lookup_int32");
319 params_type_print(p, tset_to_string(tset), fmri);
320 }
321 } else {
322 /* this is FMA event nvlist */
323 if (nvl == NULL) { /* preferences not found */
324 return;
325 }
326 for (i = 0; i < n; ++i) {
327 nvlist_t *p = *(params + i);
328
329 if (nvlist_lookup_string(p,
330 SCF_NOTIFY_PARAMS_SOURCE_NAME, &fmri) != 0)
331 fmri = NULL;
332 params_type_print(p, event, fmri);
333 }
334 }
335 }
336