xref: /illumos-gate/usr/src/cmd/pcidr/pcidr_common.c (revision bbf21555)
170025d76Sjohnny /*
270025d76Sjohnny  * CDDL HEADER START
370025d76Sjohnny  *
470025d76Sjohnny  * The contents of this file are subject to the terms of the
570025d76Sjohnny  * Common Development and Distribution License, Version 1.0 only
670025d76Sjohnny  * (the "License").  You may not use this file except in compliance
770025d76Sjohnny  * with the License.
870025d76Sjohnny  *
970025d76Sjohnny  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1070025d76Sjohnny  * or http://www.opensolaris.org/os/licensing.
1170025d76Sjohnny  * See the License for the specific language governing permissions
1270025d76Sjohnny  * and limitations under the License.
1370025d76Sjohnny  *
1470025d76Sjohnny  * When distributing Covered Code, include this CDDL HEADER in each
1570025d76Sjohnny  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1670025d76Sjohnny  * If applicable, add the following below this CDDL HEADER, with the
1770025d76Sjohnny  * fields enclosed by brackets "[]" replaced with your own identifying
1870025d76Sjohnny  * information: Portions Copyright [yyyy] [name of copyright owner]
1970025d76Sjohnny  *
2070025d76Sjohnny  * CDDL HEADER END
2170025d76Sjohnny  */
2270025d76Sjohnny /*
2370025d76Sjohnny  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
2470025d76Sjohnny  * Use is subject to license terms.
2570025d76Sjohnny  */
2670025d76Sjohnny 
2770025d76Sjohnny #include <stdio.h>
2870025d76Sjohnny #include <stdlib.h>
2970025d76Sjohnny #include <unistd.h>
3070025d76Sjohnny #include <strings.h>
3170025d76Sjohnny #include <string.h>
3270025d76Sjohnny #include <errno.h>
3370025d76Sjohnny #include <sys/param.h>
3470025d76Sjohnny #include <sys/sysevent/eventdefs.h>
3570025d76Sjohnny #include <sys/sysevent/dr.h>
3670025d76Sjohnny #include <syslog.h>
3770025d76Sjohnny #include <libnvpair.h>
3870025d76Sjohnny #include <stdarg.h>
3970025d76Sjohnny #include <assert.h>
4070025d76Sjohnny #include <sys/stat.h>
4170025d76Sjohnny #include <dlfcn.h>
4270025d76Sjohnny #include <signal.h>
4370025d76Sjohnny #include <pcidr.h>
4470025d76Sjohnny 
4570025d76Sjohnny 
4670025d76Sjohnny /*
4770025d76Sjohnny  * How dpritab is used:
4870025d76Sjohnny  * dpritab[dlvl_t value] = corresponding syslog priority
4970025d76Sjohnny  *
5070025d76Sjohnny  * Be careful of some priorities (facility + severity) that get "lost" by
5170025d76Sjohnny  * default since they have no syslog.conf entries such as daemon.info and
52*bbf21555SRichard Lowe  * daemon.debug; see syslog(3C) and syslog.conf(5) for more info
5370025d76Sjohnny  */
5470025d76Sjohnny int dpritab[] = {LOG_INFO, LOG_WARNING, LOG_NOTICE, LOG_NOTICE};
5570025d76Sjohnny int dpritab_len = sizeof (dpritab) / sizeof (dpritab[0]);
5670025d76Sjohnny 
5770025d76Sjohnny /*
5870025d76Sjohnny  * the following affects pcidr_set_logopt() which plugins should use to set
5970025d76Sjohnny  * these logging options received from the handler
6070025d76Sjohnny  */
6170025d76Sjohnny dlvl_t dlvl = MIN_DLVL;	/* verbosity */
6270025d76Sjohnny char *prg = "";		/* program name */
6370025d76Sjohnny FILE *dfp = NULL;	/* file to output messages to */
6470025d76Sjohnny int dsys = 1;		/* flag controlling output to syslog */
6570025d76Sjohnny 
6670025d76Sjohnny 
6770025d76Sjohnny void *
pcidr_malloc(size_t size)6870025d76Sjohnny pcidr_malloc(size_t size)
6970025d76Sjohnny {
7070025d76Sjohnny 	int i = 0;
7170025d76Sjohnny 	void *buf;
7270025d76Sjohnny 
7370025d76Sjohnny 	errno = 0;
7470025d76Sjohnny 	buf = malloc(size);
7570025d76Sjohnny 	if (buf != NULL)
7670025d76Sjohnny 		return (buf);
7770025d76Sjohnny 
7870025d76Sjohnny 	for (i = 0; i < PCIDR_MALLOC_CNT; i++) {
7970025d76Sjohnny 		assert(errno == EAGAIN);
8070025d76Sjohnny 		if (errno != EAGAIN)
8170025d76Sjohnny 			exit(errno);
8270025d76Sjohnny 		(void) usleep(PCIDR_MALLOC_TIME);
8370025d76Sjohnny 
8470025d76Sjohnny 		errno = 0;
8570025d76Sjohnny 		buf = malloc(size);
8670025d76Sjohnny 		if (buf != NULL)
8770025d76Sjohnny 			return (buf);
8870025d76Sjohnny 	}
8970025d76Sjohnny 
9070025d76Sjohnny 	assert(buf != NULL);
9170025d76Sjohnny 	/* exit() in case assertions are disabled (NDEBUG defined) */
9270025d76Sjohnny 	exit(errno);
9370025d76Sjohnny 	return (NULL);
9470025d76Sjohnny }
9570025d76Sjohnny 
9670025d76Sjohnny 
9770025d76Sjohnny void
dprint(dlvl_t lvl,char * fmt,...)9870025d76Sjohnny dprint(dlvl_t lvl, char *fmt, ...)
9970025d76Sjohnny {
10070025d76Sjohnny 	int buflen, rv;
10170025d76Sjohnny 	char *buf;
10270025d76Sjohnny 	va_list ap;
10370025d76Sjohnny 
10470025d76Sjohnny 	if (dlvl < lvl || (dsys == 0 && dfp == NULL))
10570025d76Sjohnny 		return;
10670025d76Sjohnny 
10770025d76Sjohnny 	va_start(ap, fmt);
10870025d76Sjohnny 	/*LINTED*/
10970025d76Sjohnny 	buflen = vsnprintf(NULL, 0, fmt, ap);
11070025d76Sjohnny 	va_end(ap);
11170025d76Sjohnny 	if (buflen <= 0)
11270025d76Sjohnny 		return;
11370025d76Sjohnny 	buflen++;
11470025d76Sjohnny 	buf = (char *)pcidr_malloc(sizeof (char) * buflen);
11570025d76Sjohnny 
11670025d76Sjohnny 	va_start(ap, fmt);
11770025d76Sjohnny 	/*LINTED*/
11870025d76Sjohnny 	rv = vsnprintf(buf, buflen, fmt, ap);
11970025d76Sjohnny 	va_end(ap);
12070025d76Sjohnny 	if (rv <= 0) {
12170025d76Sjohnny 		free(buf);
12270025d76Sjohnny 		return;
12370025d76Sjohnny 	}
12470025d76Sjohnny 
12570025d76Sjohnny #ifdef DEBUG
12670025d76Sjohnny 	if (dsys != 0)
12770025d76Sjohnny 		syslog(dpritab[lvl], "%s", buf);
12870025d76Sjohnny #endif
12970025d76Sjohnny 	if (dfp != NULL)
13070025d76Sjohnny 		(void) fprintf(dfp, "%s", buf);
13170025d76Sjohnny 
13270025d76Sjohnny 	free(buf);
13370025d76Sjohnny }
13470025d76Sjohnny 
13570025d76Sjohnny 
13670025d76Sjohnny void
pcidr_set_logopt(pcidr_logopt_t * logopt)13770025d76Sjohnny pcidr_set_logopt(pcidr_logopt_t *logopt)
13870025d76Sjohnny {
13970025d76Sjohnny 	dlvl = logopt->dlvl;
14070025d76Sjohnny 	prg = logopt->prg;
14170025d76Sjohnny 	dfp = logopt->dfp;
14270025d76Sjohnny 	dsys = logopt->dsys;
14370025d76Sjohnny }
14470025d76Sjohnny 
14570025d76Sjohnny 
14670025d76Sjohnny /*
14770025d76Sjohnny  * if <name> is recognized, function will return its type through <typep> and
14870025d76Sjohnny  * return 0; else function will return non-zero
14970025d76Sjohnny  */
15070025d76Sjohnny int
pcidr_name2type(char * name,data_type_t * typep)15170025d76Sjohnny pcidr_name2type(char *name, data_type_t *typep)
15270025d76Sjohnny {
15370025d76Sjohnny 	/* string type */
15470025d76Sjohnny 	if (strcmp(name, ATTRNM_CLASS) == 0 ||
15570025d76Sjohnny 	    strcmp(name, ATTRNM_SUBCLASS) == 0 ||
15670025d76Sjohnny 	    strcmp(name, ATTRNM_PUB_NAME) == 0 ||
15770025d76Sjohnny 	    strcmp(name, DR_REQ_TYPE) == 0 ||
15870025d76Sjohnny 	    strcmp(name, DR_AP_ID) == 0) {
15970025d76Sjohnny 		*typep = DATA_TYPE_STRING;
16070025d76Sjohnny 		return (0);
16170025d76Sjohnny 	}
16270025d76Sjohnny 
16370025d76Sjohnny 	return (1);
16470025d76Sjohnny }
16570025d76Sjohnny 
16670025d76Sjohnny 
16770025d76Sjohnny void
pcidr_print_attrlist(dlvl_t lvl,nvlist_t * attrlistp,char * prestr)16870025d76Sjohnny pcidr_print_attrlist(dlvl_t lvl, nvlist_t *attrlistp, char *prestr)
16970025d76Sjohnny {
17070025d76Sjohnny 	char *fn = "pcidr_print_attrlist";
17170025d76Sjohnny 	nvpair_t *nvpairp;
17270025d76Sjohnny 	char *valstr, *name;
17370025d76Sjohnny 	data_type_t type;
17470025d76Sjohnny 	int rv;
17570025d76Sjohnny 
17670025d76Sjohnny 	if (prestr == NULL)
17770025d76Sjohnny 		prestr = "";
17870025d76Sjohnny 
17970025d76Sjohnny 	nvpairp = NULL;
18070025d76Sjohnny 	while ((nvpairp = nvlist_next_nvpair(attrlistp, nvpairp)) != NULL) {
18170025d76Sjohnny 		type = nvpair_type(nvpairp);
18270025d76Sjohnny 		name = nvpair_name(nvpairp);
18370025d76Sjohnny 
18470025d76Sjohnny 		switch (type) {
18570025d76Sjohnny 		case DATA_TYPE_STRING:
18670025d76Sjohnny 			rv = nvpair_value_string(nvpairp, &valstr);
18770025d76Sjohnny 			if (rv != 0) {
18870025d76Sjohnny 				dprint(lvl, "%s: nvpair_value_string() "
18970025d76Sjohnny 				    "failed: name = %s, rv = %d\n",
19070025d76Sjohnny 				    fn, name, rv);
19170025d76Sjohnny 				continue;
19270025d76Sjohnny 			}
19370025d76Sjohnny 			break;
19470025d76Sjohnny 		default:
19570025d76Sjohnny 			dprint(lvl, "%s: unsupported type: name = %s, "
19670025d76Sjohnny 			    "type = 0x%x\n", fn, name, (int)type);
19770025d76Sjohnny 			continue;
19870025d76Sjohnny 		}
19970025d76Sjohnny 		dprint(lvl, "%s%s = %s\n", prestr, name, valstr);
20070025d76Sjohnny 	}
20170025d76Sjohnny }
20270025d76Sjohnny 
20370025d76Sjohnny 
20470025d76Sjohnny /*
20570025d76Sjohnny  * if one of the args matches <valstr>, return 0; else return non-zero
20670025d76Sjohnny  * args list must be NULL terminated;
20770025d76Sjohnny  * if args list is empty, this will return 0 if <valstr> is NOT empty
20870025d76Sjohnny  */
20970025d76Sjohnny int
pcidr_check_string(char * valstr,...)21070025d76Sjohnny pcidr_check_string(char *valstr, ...)
21170025d76Sjohnny {
21270025d76Sjohnny 	va_list ap;
21370025d76Sjohnny 	int rv;
21470025d76Sjohnny 	char *argstr;
21570025d76Sjohnny 
21670025d76Sjohnny 	assert(valstr != NULL);
21770025d76Sjohnny 	rv = 1;
21870025d76Sjohnny 	va_start(ap, valstr);
21970025d76Sjohnny 	if (va_arg(ap, char *) == NULL) {
22070025d76Sjohnny 		if (valstr[0] != '\0')
22170025d76Sjohnny 			rv = 0;
22270025d76Sjohnny 		goto OUT;
22370025d76Sjohnny 	}
22470025d76Sjohnny 
22570025d76Sjohnny 	va_start(ap, valstr);
22670025d76Sjohnny 	while ((argstr = va_arg(ap, char *)) != NULL) {
22770025d76Sjohnny 		if (strcmp(argstr, valstr) == 0) {
22870025d76Sjohnny 			rv = 0;
22970025d76Sjohnny 			break;
23070025d76Sjohnny 		}
23170025d76Sjohnny 	}
23270025d76Sjohnny OUT:
23370025d76Sjohnny 	va_end(ap);
23470025d76Sjohnny 	return (rv);
23570025d76Sjohnny }
23670025d76Sjohnny 
23770025d76Sjohnny 
23870025d76Sjohnny /*
23970025d76Sjohnny  * dr attribute values that the default plugin checks for;
24070025d76Sjohnny  * other plugins may also use this if they support a superset of these
24170025d76Sjohnny  * values.
24270025d76Sjohnny  * returns 0 if valid, else non-zero
24370025d76Sjohnny  */
24470025d76Sjohnny int
pcidr_check_attrs(pcidr_attrs_t * drp)24570025d76Sjohnny pcidr_check_attrs(pcidr_attrs_t *drp)
24670025d76Sjohnny {
24770025d76Sjohnny 	char *fn = "pcidr_check_attrs";
24870025d76Sjohnny 	int rv = 0;
24970025d76Sjohnny 	char *val, *name;
25070025d76Sjohnny 
25170025d76Sjohnny 	name = ATTRNM_CLASS;
25270025d76Sjohnny 	val = drp->class;
25370025d76Sjohnny 	if (pcidr_check_string(val, EC_DR, NULL) != 0) {
25470025d76Sjohnny 		dprint(DDEBUG, "%s: attribute \"%s\" has invalid value = %s\n",
25570025d76Sjohnny 		    fn, name, val);
25670025d76Sjohnny 		rv = 1;
25770025d76Sjohnny 	}
25870025d76Sjohnny 
25970025d76Sjohnny 	name = ATTRNM_SUBCLASS;
26070025d76Sjohnny 	val = drp->subclass;
26170025d76Sjohnny 	if (pcidr_check_string(val, ESC_DR_REQ, NULL) != 0) {
26270025d76Sjohnny 		dprint(DDEBUG, "%s: attribute \"%s\" has invalid value = %s\n",
26370025d76Sjohnny 		    fn, name, val);
26470025d76Sjohnny 		rv = 1;
26570025d76Sjohnny 	}
26670025d76Sjohnny 
26770025d76Sjohnny 	name = ATTRNM_PUB_NAME;
26870025d76Sjohnny 	val = drp->pub_name;
26970025d76Sjohnny 	if (pcidr_check_string(val, NULL) != 0) {
27070025d76Sjohnny 		dprint(DDEBUG, "%s: attribute \"%s\" is empty\n",
27170025d76Sjohnny 		    fn, name, val);
27270025d76Sjohnny 		rv = 1;
27370025d76Sjohnny 	}
27470025d76Sjohnny 
27570025d76Sjohnny 	name = DR_REQ_TYPE;
27670025d76Sjohnny 	val = drp->dr_req_type;
27770025d76Sjohnny 	if (pcidr_check_string(val, DR_REQ_INCOMING_RES, DR_REQ_OUTGOING_RES,
27870025d76Sjohnny 	    NULL) != 0) {
27970025d76Sjohnny 		dprint(DDEBUG, "%s: attribute \"%s\" has invalid value = %s\n",
28070025d76Sjohnny 		    fn, name, val);
28170025d76Sjohnny 		rv = 1;
28270025d76Sjohnny 	}
28370025d76Sjohnny 
28470025d76Sjohnny 	name = DR_AP_ID;
28570025d76Sjohnny 	val = drp->dr_ap_id;
28670025d76Sjohnny 	if (pcidr_check_string(drp->dr_ap_id, NULL) != 0) {
28770025d76Sjohnny 		dprint(DDEBUG, "%s: attribute \"%s\" is empty\n",
28870025d76Sjohnny 		    fn, name, val);
28970025d76Sjohnny 		rv = 1;
29070025d76Sjohnny 	}
29170025d76Sjohnny 
29270025d76Sjohnny 	return (rv);
29370025d76Sjohnny }
29470025d76Sjohnny 
29570025d76Sjohnny 
29670025d76Sjohnny /*
29770025d76Sjohnny  * get dr attributes from <listp> for the default plugin and returns
29870025d76Sjohnny  * them through <drp>;
29970025d76Sjohnny  * returns 0 on success
30070025d76Sjohnny  */
30170025d76Sjohnny int
pcidr_get_attrs(nvlist_t * attrlistp,pcidr_attrs_t * drp)30270025d76Sjohnny pcidr_get_attrs(nvlist_t *attrlistp, pcidr_attrs_t *drp)
30370025d76Sjohnny {
30470025d76Sjohnny 	char *fn = "pcidr_get_attrs";
30570025d76Sjohnny 	char *name;
30670025d76Sjohnny 	int r, rv = 0;
30770025d76Sjohnny 
30870025d76Sjohnny 	name = ATTRNM_CLASS;
30970025d76Sjohnny 	r = nvlist_lookup_string(attrlistp, name, &drp->class);
31070025d76Sjohnny 	if (r != 0) {
31170025d76Sjohnny 		dprint(DDEBUG, "%s: nvlist_lookup_string() failed for "
31270025d76Sjohnny 		    "attribute \"%s\": rv = %d\n", fn, name, r);
31370025d76Sjohnny 		rv = r;
31470025d76Sjohnny 	}
31570025d76Sjohnny 
31670025d76Sjohnny 	name = ATTRNM_SUBCLASS;
31770025d76Sjohnny 	r = nvlist_lookup_string(attrlistp, name, &drp->subclass);
31870025d76Sjohnny 	if (r != 0) {
31970025d76Sjohnny 		dprint(DDEBUG, "%s: nvlist_lookup_string() failed for "
32070025d76Sjohnny 		    "attribute \"%s\": rv = %d\n", fn, name, r);
32170025d76Sjohnny 		rv = r;
32270025d76Sjohnny 	}
32370025d76Sjohnny 
32470025d76Sjohnny 	name = ATTRNM_PUB_NAME;
32570025d76Sjohnny 	r = nvlist_lookup_string(attrlistp, name, &drp->pub_name);
32670025d76Sjohnny 	if (r != 0) {
32770025d76Sjohnny 		dprint(DDEBUG, "%s: nvlist_lookup_string() failed for "
32870025d76Sjohnny 		    "attribute \"%s\": rv = %d\n", fn, name, r);
32970025d76Sjohnny 		rv = r;
33070025d76Sjohnny 	}
33170025d76Sjohnny 
33270025d76Sjohnny 	name = DR_REQ_TYPE;
33370025d76Sjohnny 	r = nvlist_lookup_string(attrlistp, name, &drp->dr_req_type);
33470025d76Sjohnny 	if (r != 0) {
33570025d76Sjohnny 		dprint(DDEBUG, "%s: nvlist_lookup_string() failed for "
33670025d76Sjohnny 		    "attribute \"%s\": rv = %d\n", fn, name, r);
33770025d76Sjohnny 		rv = r;
33870025d76Sjohnny 	}
33970025d76Sjohnny 
34070025d76Sjohnny 	name = DR_AP_ID;
34170025d76Sjohnny 	r = nvlist_lookup_string(attrlistp, name, &drp->dr_ap_id);
34270025d76Sjohnny 	if (r != 0) {
34370025d76Sjohnny 		dprint(DDEBUG, "%s: nvlist_lookup_string() failed for "
34470025d76Sjohnny 		    "attribute \"%s\": rv = %d\n", fn, name, r);
34570025d76Sjohnny 		rv = r;
34670025d76Sjohnny 	}
34770025d76Sjohnny 
34870025d76Sjohnny 	return (rv);
34970025d76Sjohnny }
350