xref: /illumos-gate/usr/src/cmd/pcidr/pcidr_common.c (revision 70025d76)
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