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