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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <strings.h> 33 #include <string.h> 34 #include <errno.h> 35 #include <sys/param.h> 36 #include <sys/sysevent/eventdefs.h> 37 #include <sys/sysevent/dr.h> 38 #include <syslog.h> 39 #include <libnvpair.h> 40 #include <stdarg.h> 41 #include <assert.h> 42 #include <sys/stat.h> 43 #include <dlfcn.h> 44 #include <signal.h> 45 #include <pcidr.h> 46 47 48 /* 49 * How dpritab is used: 50 * dpritab[dlvl_t value] = corresponding syslog priority 51 * 52 * Be careful of some priorities (facility + severity) that get "lost" by 53 * default since they have no syslog.conf entries such as daemon.info and 54 * daemon.debug; see syslog(3C) and syslog.conf(4) for more info 55 */ 56 int dpritab[] = {LOG_INFO, LOG_WARNING, LOG_NOTICE, LOG_NOTICE}; 57 int dpritab_len = sizeof (dpritab) / sizeof (dpritab[0]); 58 59 /* 60 * the following affects pcidr_set_logopt() which plugins should use to set 61 * these logging options received from the handler 62 */ 63 dlvl_t dlvl = MIN_DLVL; /* verbosity */ 64 char *prg = ""; /* program name */ 65 FILE *dfp = NULL; /* file to output messages to */ 66 int dsys = 1; /* flag controlling output to syslog */ 67 68 69 void * 70 pcidr_malloc(size_t size) 71 { 72 int i = 0; 73 void *buf; 74 75 errno = 0; 76 buf = malloc(size); 77 if (buf != NULL) 78 return (buf); 79 80 for (i = 0; i < PCIDR_MALLOC_CNT; i++) { 81 assert(errno == EAGAIN); 82 if (errno != EAGAIN) 83 exit(errno); 84 (void) usleep(PCIDR_MALLOC_TIME); 85 86 errno = 0; 87 buf = malloc(size); 88 if (buf != NULL) 89 return (buf); 90 } 91 92 assert(buf != NULL); 93 /* exit() in case assertions are disabled (NDEBUG defined) */ 94 exit(errno); 95 return (NULL); 96 } 97 98 99 void 100 dprint(dlvl_t lvl, char *fmt, ...) 101 { 102 int buflen, rv; 103 char *buf; 104 va_list ap; 105 106 if (dlvl < lvl || (dsys == 0 && dfp == NULL)) 107 return; 108 109 va_start(ap, fmt); 110 /*LINTED*/ 111 buflen = vsnprintf(NULL, 0, fmt, ap); 112 va_end(ap); 113 if (buflen <= 0) 114 return; 115 buflen++; 116 buf = (char *)pcidr_malloc(sizeof (char) * buflen); 117 118 va_start(ap, fmt); 119 /*LINTED*/ 120 rv = vsnprintf(buf, buflen, fmt, ap); 121 va_end(ap); 122 if (rv <= 0) { 123 free(buf); 124 return; 125 } 126 127 #ifdef DEBUG 128 if (dsys != 0) 129 syslog(dpritab[lvl], "%s", buf); 130 #endif 131 if (dfp != NULL) 132 (void) fprintf(dfp, "%s", buf); 133 134 free(buf); 135 } 136 137 138 void 139 pcidr_set_logopt(pcidr_logopt_t *logopt) 140 { 141 dlvl = logopt->dlvl; 142 prg = logopt->prg; 143 dfp = logopt->dfp; 144 dsys = logopt->dsys; 145 } 146 147 148 /* 149 * if <name> is recognized, function will return its type through <typep> and 150 * return 0; else function will return non-zero 151 */ 152 int 153 pcidr_name2type(char *name, data_type_t *typep) 154 { 155 /* string type */ 156 if (strcmp(name, ATTRNM_CLASS) == 0 || 157 strcmp(name, ATTRNM_SUBCLASS) == 0 || 158 strcmp(name, ATTRNM_PUB_NAME) == 0 || 159 strcmp(name, DR_REQ_TYPE) == 0 || 160 strcmp(name, DR_AP_ID) == 0) { 161 *typep = DATA_TYPE_STRING; 162 return (0); 163 } 164 165 return (1); 166 } 167 168 169 void 170 pcidr_print_attrlist(dlvl_t lvl, nvlist_t *attrlistp, char *prestr) 171 { 172 char *fn = "pcidr_print_attrlist"; 173 nvpair_t *nvpairp; 174 char *valstr, *name; 175 data_type_t type; 176 int rv; 177 178 if (prestr == NULL) 179 prestr = ""; 180 181 nvpairp = NULL; 182 while ((nvpairp = nvlist_next_nvpair(attrlistp, nvpairp)) != NULL) { 183 type = nvpair_type(nvpairp); 184 name = nvpair_name(nvpairp); 185 186 switch (type) { 187 case DATA_TYPE_STRING: 188 rv = nvpair_value_string(nvpairp, &valstr); 189 if (rv != 0) { 190 dprint(lvl, "%s: nvpair_value_string() " 191 "failed: name = %s, rv = %d\n", 192 fn, name, rv); 193 continue; 194 } 195 break; 196 default: 197 dprint(lvl, "%s: unsupported type: name = %s, " 198 "type = 0x%x\n", fn, name, (int)type); 199 continue; 200 } 201 dprint(lvl, "%s%s = %s\n", prestr, name, valstr); 202 } 203 } 204 205 206 /* 207 * if one of the args matches <valstr>, return 0; else return non-zero 208 * args list must be NULL terminated; 209 * if args list is empty, this will return 0 if <valstr> is NOT empty 210 */ 211 int 212 pcidr_check_string(char *valstr, ...) 213 { 214 va_list ap; 215 int rv; 216 char *argstr; 217 218 assert(valstr != NULL); 219 rv = 1; 220 va_start(ap, valstr); 221 if (va_arg(ap, char *) == NULL) { 222 if (valstr[0] != '\0') 223 rv = 0; 224 goto OUT; 225 } 226 227 va_start(ap, valstr); 228 while ((argstr = va_arg(ap, char *)) != NULL) { 229 if (strcmp(argstr, valstr) == 0) { 230 rv = 0; 231 break; 232 } 233 } 234 OUT: 235 va_end(ap); 236 return (rv); 237 } 238 239 240 /* 241 * dr attribute values that the default plugin checks for; 242 * other plugins may also use this if they support a superset of these 243 * values. 244 * returns 0 if valid, else non-zero 245 */ 246 int 247 pcidr_check_attrs(pcidr_attrs_t *drp) 248 { 249 char *fn = "pcidr_check_attrs"; 250 int rv = 0; 251 char *val, *name; 252 253 name = ATTRNM_CLASS; 254 val = drp->class; 255 if (pcidr_check_string(val, EC_DR, NULL) != 0) { 256 dprint(DDEBUG, "%s: attribute \"%s\" has invalid value = %s\n", 257 fn, name, val); 258 rv = 1; 259 } 260 261 name = ATTRNM_SUBCLASS; 262 val = drp->subclass; 263 if (pcidr_check_string(val, ESC_DR_REQ, NULL) != 0) { 264 dprint(DDEBUG, "%s: attribute \"%s\" has invalid value = %s\n", 265 fn, name, val); 266 rv = 1; 267 } 268 269 name = ATTRNM_PUB_NAME; 270 val = drp->pub_name; 271 if (pcidr_check_string(val, NULL) != 0) { 272 dprint(DDEBUG, "%s: attribute \"%s\" is empty\n", 273 fn, name, val); 274 rv = 1; 275 } 276 277 name = DR_REQ_TYPE; 278 val = drp->dr_req_type; 279 if (pcidr_check_string(val, DR_REQ_INCOMING_RES, DR_REQ_OUTGOING_RES, 280 NULL) != 0) { 281 dprint(DDEBUG, "%s: attribute \"%s\" has invalid value = %s\n", 282 fn, name, val); 283 rv = 1; 284 } 285 286 name = DR_AP_ID; 287 val = drp->dr_ap_id; 288 if (pcidr_check_string(drp->dr_ap_id, NULL) != 0) { 289 dprint(DDEBUG, "%s: attribute \"%s\" is empty\n", 290 fn, name, val); 291 rv = 1; 292 } 293 294 return (rv); 295 } 296 297 298 /* 299 * get dr attributes from <listp> for the default plugin and returns 300 * them through <drp>; 301 * returns 0 on success 302 */ 303 int 304 pcidr_get_attrs(nvlist_t *attrlistp, pcidr_attrs_t *drp) 305 { 306 char *fn = "pcidr_get_attrs"; 307 char *name; 308 int r, rv = 0; 309 310 name = ATTRNM_CLASS; 311 r = nvlist_lookup_string(attrlistp, name, &drp->class); 312 if (r != 0) { 313 dprint(DDEBUG, "%s: nvlist_lookup_string() failed for " 314 "attribute \"%s\": rv = %d\n", fn, name, r); 315 rv = r; 316 } 317 318 name = ATTRNM_SUBCLASS; 319 r = nvlist_lookup_string(attrlistp, name, &drp->subclass); 320 if (r != 0) { 321 dprint(DDEBUG, "%s: nvlist_lookup_string() failed for " 322 "attribute \"%s\": rv = %d\n", fn, name, r); 323 rv = r; 324 } 325 326 name = ATTRNM_PUB_NAME; 327 r = nvlist_lookup_string(attrlistp, name, &drp->pub_name); 328 if (r != 0) { 329 dprint(DDEBUG, "%s: nvlist_lookup_string() failed for " 330 "attribute \"%s\": rv = %d\n", fn, name, r); 331 rv = r; 332 } 333 334 name = DR_REQ_TYPE; 335 r = nvlist_lookup_string(attrlistp, name, &drp->dr_req_type); 336 if (r != 0) { 337 dprint(DDEBUG, "%s: nvlist_lookup_string() failed for " 338 "attribute \"%s\": rv = %d\n", fn, name, r); 339 rv = r; 340 } 341 342 name = DR_AP_ID; 343 r = nvlist_lookup_string(attrlistp, name, &drp->dr_ap_id); 344 if (r != 0) { 345 dprint(DDEBUG, "%s: nvlist_lookup_string() failed for " 346 "attribute \"%s\": rv = %d\n", fn, name, r); 347 rv = r; 348 } 349 350 return (rv); 351 } 352