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