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 * 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 * 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 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 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 * 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 * 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 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 * 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 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 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 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 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 has_output = 1; 265 266 safe_printf(gettext(" Notification Type: %s\n"), 267 nvpair_name(tnvp)); 268 269 if (nvlist_lookup_boolean_array(nvl, PARAM_ACTIVE, &a, &n) != 0) 270 uu_warn(gettext("Missing 'active' property")); 271 else 272 safe_printf(gettext(" Active: %s\n"), 273 *a ? "true" : "false"); 274 275 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 276 nvp = nvlist_next_nvpair(nvl, nvp)) { 277 if (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY) 278 continue; 279 nvpair_print(nvp); 280 } 281 safe_printf("\n"); 282 } 283 } 284 285 void 286 listnotify_print(nvlist_t *nvl, const char *event) 287 { 288 char *fmri; 289 nvlist_t **params; 290 size_t n; 291 int32_t tset; 292 int i; 293 294 /* 295 * Check the nvl we got is from a version we understand 296 */ 297 if (nvl != NULL && notify_params_get_version(nvl) != 298 SCF_NOTIFY_PARAMS_VERSION) 299 uu_die(gettext("libscf(3LIB) mismatch\n")); 300 301 if (nvl != NULL && nvlist_lookup_nvlist_array(nvl, SCF_NOTIFY_PARAMS, 302 ¶ms, &n) != 0) 303 /* Sanity check. If we get here nvl is bad! */ 304 uu_die(gettext("nvlist_lookup_nvlist_array\n")); 305 306 if (event == NULL) { 307 /* this is an SMF state transition nvlist */ 308 for (i = 0; i < n; ++i) { 309 nvlist_t *p = *(params + i); 310 311 if (nvlist_lookup_string(p, 312 SCF_NOTIFY_PARAMS_SOURCE_NAME, &fmri) != 0) 313 fmri = NULL; 314 if (nvlist_lookup_int32(p, SCF_NOTIFY_NAME_TSET, 315 &tset) != 0) 316 uu_die("nvlist_lookup_int32"); 317 params_type_print(p, tset_to_string(tset), fmri); 318 } 319 } else { 320 /* this is FMA event nvlist */ 321 if (nvl == NULL) { /* preferences not found */ 322 return; 323 } 324 for (i = 0; i < n; ++i) { 325 nvlist_t *p = *(params + i); 326 327 if (nvlist_lookup_string(p, 328 SCF_NOTIFY_PARAMS_SOURCE_NAME, &fmri) != 0) 329 fmri = NULL; 330 params_type_print(p, event, fmri); 331 } 332 } 333 }