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