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 <strings.h> 27 #include <libscf.h> 28 #include <fm/fmd_api.h> 29 #include <fm/libtopo.h> 30 #include <fm/libfmevent.h> 31 32 #include "fmevt.h" 33 34 /* 35 * Post-processing according to the FMEV_RULESET_SMF ruleset. 36 * 37 * Raw event we expect: 38 * 39 * ========================================================================== 40 * Class: "state-transition" 41 * Subclasses: The new state, one of SCF_STATE_STRING_* from libscf.h 42 * Attr: 43 * Name DATA_TYPE_* Description 44 * ------------ --------------- --------------------------------------------- 45 * fmri STRING svc:/... (svc scheme shorthand version) 46 * transition INT32 (old_state << 16) | new_state 47 * reason-version UINT32 reason-short namespace version 48 * reason-short STRING Short/keyword reason for transition 49 * reason-long STRING Long-winded reason for the transition 50 * ========================================================================== 51 * 52 * Protocol event components we return: 53 * 54 * ========================================================================== 55 * Class: ireport.os.smf.state-transition.<new-state> 56 * Attr: 57 * Name DATA_TYPE_* Description 58 * ------------ --------------- ---------------------------------------- 59 * svc NVLIST "svc" scheme FMRI of affected service instance 60 * svc-string STRING SMF FMRI in short string form svc:/foo/bar 61 * from-state STRING Previous state; SCF_STATE_STRING_* 62 * to-state STRING New state; SCF_STATE_STRING_* 63 * reason-version UINT32 reason-short namespace version 64 * reason-short STRING Short/keyword reason for transition 65 * reason-long STRING Long-winded reason for the transition 66 * ========================================================================== 67 */ 68 69 /* 70 * svc.startd generates events using the FMRI shorthand (svc:/foo/bar) 71 * instead of the standard form (svc:///foo/bar). This function converts to 72 * the standard representation. The caller must free the allocated string. 73 */ 74 static char * 75 shortfmri_to_fmristr(fmd_hdl_t *hdl, const char *shortfmristr) 76 { 77 size_t len; 78 char *fmristr; 79 80 if (strncmp(shortfmristr, "svc:/", 5) != 0) 81 return (NULL); 82 83 len = strlen(shortfmristr) + 3; 84 fmristr = fmd_hdl_alloc(hdl, len, FMD_SLEEP); 85 (void) snprintf(fmristr, len, "svc:///%s", shortfmristr + 5); 86 87 return (fmristr); 88 } 89 90 /* 91 * Convert a shorthand svc FMRI into a full svc FMRI nvlist 92 */ 93 static nvlist_t * 94 shortfmri_to_fmri(fmd_hdl_t *hdl, const char *shortfmristr) 95 { 96 nvlist_t *ret, *fmri; 97 topo_hdl_t *thp; 98 char *fmristr; 99 int err; 100 101 if ((fmristr = shortfmri_to_fmristr(hdl, shortfmristr)) == NULL) 102 return (NULL); 103 104 thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION); 105 106 if (topo_fmri_str2nvl(thp, fmristr, &fmri, &err) != 0) { 107 fmd_hdl_error(hdl, "failed to convert '%s' to nvlist\n", 108 fmristr); 109 fmd_hdl_strfree(hdl, fmristr); 110 fmd_hdl_topo_rele(hdl, thp); 111 return (NULL); 112 } 113 114 fmd_hdl_strfree(hdl, fmristr); 115 116 if ((ret = fmd_nvl_dup(hdl, fmri, FMD_SLEEP)) == NULL) { 117 fmd_hdl_error(hdl, "failed to dup fmri\n"); 118 nvlist_free(fmri); 119 fmd_hdl_topo_rele(hdl, thp); 120 return (NULL); 121 } 122 123 nvlist_free(fmri); 124 fmd_hdl_topo_rele(hdl, thp); 125 126 return (ret); 127 } 128 129 /*ARGSUSED*/ 130 uint_t 131 fmevt_pp_smf(char *classes[FMEVT_FANOUT_MAX], 132 nvlist_t *attr[FMEVT_FANOUT_MAX], const char *ruleset, 133 const nvlist_t *detector, nvlist_t *rawattr, 134 const struct fmevt_ppargs *eap) 135 { 136 int32_t transition, from, to; 137 const char *fromstr, *tostr; 138 char *svcname, *rsn, *rsnl; 139 nvlist_t *myattr; 140 nvlist_t *fmri; 141 uint32_t ver; 142 143 if (!fmd_prop_get_int32(fmevt_hdl, "inbound_postprocess_smf")) 144 return (0); 145 146 if (rawattr == NULL || 147 strcmp(eap->pp_rawclass, "state-transition") != 0 || 148 nvlist_lookup_string(rawattr, "fmri", &svcname) != 0 || 149 nvlist_lookup_int32(rawattr, "transition", &transition) != 0 || 150 nvlist_lookup_string(rawattr, "reason-short", &rsn) != 0 || 151 nvlist_lookup_string(rawattr, "reason-long", &rsnl) != 0 || 152 nvlist_lookup_uint32(rawattr, "reason-version", &ver) != 0) 153 return (0); 154 155 from = transition >> 16; 156 to = transition & 0xffff; 157 158 fromstr = smf_state_to_string(from); 159 tostr = smf_state_to_string(to); 160 161 if (fromstr == NULL || tostr == NULL) 162 return (0); 163 164 if (strcmp(eap->pp_rawsubclass, tostr) != 0) 165 return (0); 166 167 if ((fmri = shortfmri_to_fmri(fmevt_hdl, svcname)) == NULL) 168 return (0); 169 170 if (snprintf(classes[0], FMEVT_MAX_CLASS, "%s.%s.%s.%s", 171 FM_IREPORT_CLASS, "os.smf", eap->pp_rawclass, 172 eap->pp_rawsubclass) >= FMEVT_MAX_CLASS - 1) 173 return (0); 174 175 if ((myattr = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP)) == NULL) 176 return (0); 177 178 if (nvlist_add_nvlist(myattr, "svc", fmri) != 0 || 179 nvlist_add_string(myattr, "svc-string", svcname) != 0 || 180 nvlist_add_string(myattr, "from-state", fromstr) != 0 || 181 nvlist_add_string(myattr, "to-state", tostr) != 0 || 182 nvlist_add_uint32(myattr, "reason-version", ver) != 0 || 183 nvlist_add_string(myattr, "reason-short", rsn) != 0 || 184 nvlist_add_string(myattr, "reason-long", rsnl) != 0) { 185 nvlist_free(fmri); 186 nvlist_free(myattr); 187 return (0); 188 } 189 190 attr[0] = myattr; 191 nvlist_free(fmri); 192 193 return (1); 194 } 195