1*f6e214c7SGavin Maltby /*
2*f6e214c7SGavin Maltby  * CDDL HEADER START
3*f6e214c7SGavin Maltby  *
4*f6e214c7SGavin Maltby  * The contents of this file are subject to the terms of the
5*f6e214c7SGavin Maltby  * Common Development and Distribution License (the "License").
6*f6e214c7SGavin Maltby  * You may not use this file except in compliance with the License.
7*f6e214c7SGavin Maltby  *
8*f6e214c7SGavin Maltby  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*f6e214c7SGavin Maltby  * or http://www.opensolaris.org/os/licensing.
10*f6e214c7SGavin Maltby  * See the License for the specific language governing permissions
11*f6e214c7SGavin Maltby  * and limitations under the License.
12*f6e214c7SGavin Maltby  *
13*f6e214c7SGavin Maltby  * When distributing Covered Code, include this CDDL HEADER in each
14*f6e214c7SGavin Maltby  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*f6e214c7SGavin Maltby  * If applicable, add the following below this CDDL HEADER, with the
16*f6e214c7SGavin Maltby  * fields enclosed by brackets "[]" replaced with your own identifying
17*f6e214c7SGavin Maltby  * information: Portions Copyright [yyyy] [name of copyright owner]
18*f6e214c7SGavin Maltby  *
19*f6e214c7SGavin Maltby  * CDDL HEADER END
20*f6e214c7SGavin Maltby  */
21*f6e214c7SGavin Maltby 
22*f6e214c7SGavin Maltby /*
23*f6e214c7SGavin Maltby  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*f6e214c7SGavin Maltby  */
25*f6e214c7SGavin Maltby 
26*f6e214c7SGavin Maltby #include <strings.h>
27*f6e214c7SGavin Maltby #include <libscf.h>
28*f6e214c7SGavin Maltby #include <fm/fmd_api.h>
29*f6e214c7SGavin Maltby #include <fm/libtopo.h>
30*f6e214c7SGavin Maltby #include <fm/libfmevent.h>
31*f6e214c7SGavin Maltby 
32*f6e214c7SGavin Maltby #include "fmevt.h"
33*f6e214c7SGavin Maltby 
34*f6e214c7SGavin Maltby /*
35*f6e214c7SGavin Maltby  * Post-processing according to the FMEV_RULESET_SMF ruleset.
36*f6e214c7SGavin Maltby  *
37*f6e214c7SGavin Maltby  * Raw event we expect:
38*f6e214c7SGavin Maltby  *
39*f6e214c7SGavin Maltby  * ==========================================================================
40*f6e214c7SGavin Maltby  * Class: "state-transition"
41*f6e214c7SGavin Maltby  * Subclasses: The new state, one of SCF_STATE_STRING_* from libscf.h
42*f6e214c7SGavin Maltby  * Attr:
43*f6e214c7SGavin Maltby  * Name		DATA_TYPE_*	Description
44*f6e214c7SGavin Maltby  * ------------ --------------- ---------------------------------------------
45*f6e214c7SGavin Maltby  * fmri		STRING		svc:/... (svc scheme shorthand version)
46*f6e214c7SGavin Maltby  * transition	INT32		(old_state << 16) | new_state
47*f6e214c7SGavin Maltby  * reason-version UINT32	reason-short namespace version
48*f6e214c7SGavin Maltby  * reason-short	STRING		Short/keyword reason for transition
49*f6e214c7SGavin Maltby  * reason-long	STRING		Long-winded reason for the transition
50*f6e214c7SGavin Maltby  * ==========================================================================
51*f6e214c7SGavin Maltby  *
52*f6e214c7SGavin Maltby  * Protocol event components we return:
53*f6e214c7SGavin Maltby  *
54*f6e214c7SGavin Maltby  * ==========================================================================
55*f6e214c7SGavin Maltby  * Class: ireport.os.smf.state-transition.<new-state>
56*f6e214c7SGavin Maltby  * Attr:
57*f6e214c7SGavin Maltby  * Name		DATA_TYPE_*	Description
58*f6e214c7SGavin Maltby  * ------------ --------------- ----------------------------------------
59*f6e214c7SGavin Maltby  * svc		NVLIST		"svc" scheme FMRI of affected service instance
60*f6e214c7SGavin Maltby  * svc-string	STRING		SMF FMRI in short string form svc:/foo/bar
61*f6e214c7SGavin Maltby  * from-state	STRING		Previous state; SCF_STATE_STRING_*
62*f6e214c7SGavin Maltby  * to-state	STRING		New state; SCF_STATE_STRING_*
63*f6e214c7SGavin Maltby  * reason-version UINT32	reason-short namespace version
64*f6e214c7SGavin Maltby  * reason-short	STRING		Short/keyword reason for transition
65*f6e214c7SGavin Maltby  * reason-long	STRING		Long-winded reason for the transition
66*f6e214c7SGavin Maltby  * ==========================================================================
67*f6e214c7SGavin Maltby  */
68*f6e214c7SGavin Maltby 
69*f6e214c7SGavin Maltby /*
70*f6e214c7SGavin Maltby  * svc.startd generates events using the FMRI shorthand (svc:/foo/bar)
71*f6e214c7SGavin Maltby  * instead of the standard form (svc:///foo/bar).  This function converts to
72*f6e214c7SGavin Maltby  * the standard representation.  The caller must free the allocated string.
73*f6e214c7SGavin Maltby  */
74*f6e214c7SGavin Maltby static char *
shortfmri_to_fmristr(fmd_hdl_t * hdl,const char * shortfmristr)75*f6e214c7SGavin Maltby shortfmri_to_fmristr(fmd_hdl_t *hdl, const char *shortfmristr)
76*f6e214c7SGavin Maltby {
77*f6e214c7SGavin Maltby 	size_t len;
78*f6e214c7SGavin Maltby 	char *fmristr;
79*f6e214c7SGavin Maltby 
80*f6e214c7SGavin Maltby 	if (strncmp(shortfmristr, "svc:/", 5) != 0)
81*f6e214c7SGavin Maltby 		return (NULL);
82*f6e214c7SGavin Maltby 
83*f6e214c7SGavin Maltby 	len = strlen(shortfmristr) + 3;
84*f6e214c7SGavin Maltby 	fmristr = fmd_hdl_alloc(hdl, len, FMD_SLEEP);
85*f6e214c7SGavin Maltby 	(void) snprintf(fmristr, len, "svc:///%s", shortfmristr + 5);
86*f6e214c7SGavin Maltby 
87*f6e214c7SGavin Maltby 	return (fmristr);
88*f6e214c7SGavin Maltby }
89*f6e214c7SGavin Maltby 
90*f6e214c7SGavin Maltby /*
91*f6e214c7SGavin Maltby  * Convert a shorthand svc FMRI into a full svc FMRI nvlist
92*f6e214c7SGavin Maltby  */
93*f6e214c7SGavin Maltby static nvlist_t *
shortfmri_to_fmri(fmd_hdl_t * hdl,const char * shortfmristr)94*f6e214c7SGavin Maltby shortfmri_to_fmri(fmd_hdl_t *hdl, const char *shortfmristr)
95*f6e214c7SGavin Maltby {
96*f6e214c7SGavin Maltby 	nvlist_t *ret, *fmri;
97*f6e214c7SGavin Maltby 	topo_hdl_t *thp;
98*f6e214c7SGavin Maltby 	char *fmristr;
99*f6e214c7SGavin Maltby 	int err;
100*f6e214c7SGavin Maltby 
101*f6e214c7SGavin Maltby 	if ((fmristr = shortfmri_to_fmristr(hdl, shortfmristr)) == NULL)
102*f6e214c7SGavin Maltby 		return (NULL);
103*f6e214c7SGavin Maltby 
104*f6e214c7SGavin Maltby 	thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION);
105*f6e214c7SGavin Maltby 
106*f6e214c7SGavin Maltby 	if (topo_fmri_str2nvl(thp, fmristr, &fmri, &err) != 0) {
107*f6e214c7SGavin Maltby 		fmd_hdl_error(hdl, "failed to convert '%s' to nvlist\n",
108*f6e214c7SGavin Maltby 		    fmristr);
109*f6e214c7SGavin Maltby 		fmd_hdl_strfree(hdl, fmristr);
110*f6e214c7SGavin Maltby 		fmd_hdl_topo_rele(hdl, thp);
111*f6e214c7SGavin Maltby 		return (NULL);
112*f6e214c7SGavin Maltby 	}
113*f6e214c7SGavin Maltby 
114*f6e214c7SGavin Maltby 	fmd_hdl_strfree(hdl, fmristr);
115*f6e214c7SGavin Maltby 
116*f6e214c7SGavin Maltby 	if ((ret = fmd_nvl_dup(hdl, fmri, FMD_SLEEP)) == NULL) {
117*f6e214c7SGavin Maltby 		fmd_hdl_error(hdl, "failed to dup fmri\n");
118*f6e214c7SGavin Maltby 		nvlist_free(fmri);
119*f6e214c7SGavin Maltby 		fmd_hdl_topo_rele(hdl, thp);
120*f6e214c7SGavin Maltby 		return (NULL);
121*f6e214c7SGavin Maltby 	}
122*f6e214c7SGavin Maltby 
123*f6e214c7SGavin Maltby 	nvlist_free(fmri);
124*f6e214c7SGavin Maltby 	fmd_hdl_topo_rele(hdl, thp);
125*f6e214c7SGavin Maltby 
126*f6e214c7SGavin Maltby 	return (ret);
127*f6e214c7SGavin Maltby }
128*f6e214c7SGavin Maltby 
129*f6e214c7SGavin Maltby /*ARGSUSED*/
130*f6e214c7SGavin Maltby uint_t
fmevt_pp_smf(char * classes[FMEVT_FANOUT_MAX],nvlist_t * attr[FMEVT_FANOUT_MAX],const char * ruleset,const nvlist_t * detector,nvlist_t * rawattr,const struct fmevt_ppargs * eap)131*f6e214c7SGavin Maltby fmevt_pp_smf(char *classes[FMEVT_FANOUT_MAX],
132*f6e214c7SGavin Maltby     nvlist_t *attr[FMEVT_FANOUT_MAX], const char *ruleset,
133*f6e214c7SGavin Maltby     const nvlist_t *detector, nvlist_t *rawattr,
134*f6e214c7SGavin Maltby     const struct fmevt_ppargs *eap)
135*f6e214c7SGavin Maltby {
136*f6e214c7SGavin Maltby 	int32_t transition, from, to;
137*f6e214c7SGavin Maltby 	const char *fromstr, *tostr;
138*f6e214c7SGavin Maltby 	char *svcname, *rsn, *rsnl;
139*f6e214c7SGavin Maltby 	nvlist_t *myattr;
140*f6e214c7SGavin Maltby 	nvlist_t *fmri;
141*f6e214c7SGavin Maltby 	uint32_t ver;
142*f6e214c7SGavin Maltby 
143*f6e214c7SGavin Maltby 	if (!fmd_prop_get_int32(fmevt_hdl, "inbound_postprocess_smf"))
144*f6e214c7SGavin Maltby 		return (0);
145*f6e214c7SGavin Maltby 
146*f6e214c7SGavin Maltby 	if (rawattr == NULL ||
147*f6e214c7SGavin Maltby 	    strcmp(eap->pp_rawclass, "state-transition") != 0 ||
148*f6e214c7SGavin Maltby 	    nvlist_lookup_string(rawattr, "fmri", &svcname) != 0 ||
149*f6e214c7SGavin Maltby 	    nvlist_lookup_int32(rawattr, "transition", &transition) != 0 ||
150*f6e214c7SGavin Maltby 	    nvlist_lookup_string(rawattr, "reason-short", &rsn) != 0 ||
151*f6e214c7SGavin Maltby 	    nvlist_lookup_string(rawattr, "reason-long", &rsnl) != 0 ||
152*f6e214c7SGavin Maltby 	    nvlist_lookup_uint32(rawattr, "reason-version", &ver) != 0)
153*f6e214c7SGavin Maltby 		return (0);
154*f6e214c7SGavin Maltby 
155*f6e214c7SGavin Maltby 	from = transition >> 16;
156*f6e214c7SGavin Maltby 	to = transition & 0xffff;
157*f6e214c7SGavin Maltby 
158*f6e214c7SGavin Maltby 	fromstr = smf_state_to_string(from);
159*f6e214c7SGavin Maltby 	tostr = smf_state_to_string(to);
160*f6e214c7SGavin Maltby 
161*f6e214c7SGavin Maltby 	if (fromstr == NULL || tostr == NULL)
162*f6e214c7SGavin Maltby 		return (0);
163*f6e214c7SGavin Maltby 
164*f6e214c7SGavin Maltby 	if (strcmp(eap->pp_rawsubclass, tostr) != 0)
165*f6e214c7SGavin Maltby 		return (0);
166*f6e214c7SGavin Maltby 
167*f6e214c7SGavin Maltby 	if ((fmri = shortfmri_to_fmri(fmevt_hdl, svcname)) == NULL)
168*f6e214c7SGavin Maltby 		return (0);
169*f6e214c7SGavin Maltby 
170*f6e214c7SGavin Maltby 	if (snprintf(classes[0], FMEVT_MAX_CLASS, "%s.%s.%s.%s",
171*f6e214c7SGavin Maltby 	    FM_IREPORT_CLASS, "os.smf", eap->pp_rawclass,
172*f6e214c7SGavin Maltby 	    eap->pp_rawsubclass) >= FMEVT_MAX_CLASS - 1)
173*f6e214c7SGavin Maltby 		return (0);
174*f6e214c7SGavin Maltby 
175*f6e214c7SGavin Maltby 	if ((myattr = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP)) == NULL)
176*f6e214c7SGavin Maltby 		return (0);
177*f6e214c7SGavin Maltby 
178*f6e214c7SGavin Maltby 	if (nvlist_add_nvlist(myattr, "svc", fmri) != 0 ||
179*f6e214c7SGavin Maltby 	    nvlist_add_string(myattr, "svc-string", svcname) != 0 ||
180*f6e214c7SGavin Maltby 	    nvlist_add_string(myattr, "from-state", fromstr) != 0 ||
181*f6e214c7SGavin Maltby 	    nvlist_add_string(myattr, "to-state", tostr) != 0 ||
182*f6e214c7SGavin Maltby 	    nvlist_add_uint32(myattr, "reason-version", ver) != 0 ||
183*f6e214c7SGavin Maltby 	    nvlist_add_string(myattr, "reason-short", rsn) != 0 ||
184*f6e214c7SGavin Maltby 	    nvlist_add_string(myattr, "reason-long", rsnl) != 0) {
185*f6e214c7SGavin Maltby 		nvlist_free(fmri);
186*f6e214c7SGavin Maltby 		nvlist_free(myattr);
187*f6e214c7SGavin Maltby 		return (0);
188*f6e214c7SGavin Maltby 	}
189*f6e214c7SGavin Maltby 
190*f6e214c7SGavin Maltby 	attr[0] = myattr;
191*f6e214c7SGavin Maltby 	nvlist_free(fmri);
192*f6e214c7SGavin Maltby 
193*f6e214c7SGavin Maltby 	return (1);
194*f6e214c7SGavin Maltby }
195