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