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