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